Estoy construyendo un sistema de control de versiones de documentos personalizados en mi página web.
Para esto, tengo 2 mesas " vrm_document
" y " vrm_document_active_document
". La primera tabla contiene todos los documentos en mi sitio web, mientras que la segunda mesa me dice que el documento es la versión activa de la que el usuario, por lo que la segunda tabla contiene el vrm_document_id
campo y un user_id
campo. Documentos activos se indican con el parent_vrm_document_id
ser no es NULL.
Tengo 2 tipos de documentos:
- documentos por defecto
- Los documentos cargados por los propios usuarios
Cada documento que se carga contiene versiones, y min. 1 y max. 1 versión tiene que ser activa en todo momento para el usuario. Así, la segunda tabla vrm_document_active_document
contendrá siempre la vrm_document_id
combina con la user_id
de los documentos cargados por el propio usuario.
Sin embargo, el problema reside en el hecho de que los documentos son documentos predeterminados que son proporcionados por mi página web y será siempre al alcance de todos. Cuando un usuario no tiene su propia versión de un documento predeterminado, el documento predeterminado se convertirá en la versión activa para ese usuario por defecto. Esto está implicado. Para los documentos activos que no inserte filas de la vrm_document_active_document
tabla. Esto significa que si no hay versiones de un documento predeterminado para el usuario activo, el documento predeterminado se convierte en la versión activa por defecto para ese usuario.
Cuando se visualizan los documentos con sus versiones para el usuario, quiero mostrar todas las versiones en una lista bajo la otra, en la que aparece por primera vez la versión activa, y luego los otros están ordenadas en la última hora de modificación.
La siguiente consulta me da los resultados correctos para los documentos que no son documentos por defecto:
SELECT vd.*
FROM `vrm_document` AS `vd`
LEFT JOIN vrm_document_active_document AS vdad ON (vd.vrm_document_id = vdad.vrm_document_id AND vd.user_id = vdad.user_id)
WHERE ((`vd`.`parent_vrm_document_id` = 1 AND `vd`.`user_id` IN (2,18,21)) OR (`vd`.`vrm_document_id` = 1 ) )
ORDER BY vdad.vrm_document_id DESC, vd.timestamp_modified_utc DESC
Sin embargo, como se puede ver a partir de la consulta, si imaginamos que el documento de identificación 1 al ser un documento por defecto, todos los campos de la vrm_document_active_document
tabla contendrá NULL, y por lo tanto se va a clasificar en base a la hora de modificación.
El siguiente es (en pseudo-código) lo que necesito para lograr, es esto posible utilizando SQL MariaDB?
ORDER BY:
- si todos los valores == NULL entonces el valor con default_document es primero, para luego por modified_utc
- Para lo demás por modified_utc
DB violín: https://www.db-fiddle.com/f/71TUvdxFgFLhdncgo4BRre/1
EDIT: DB violín añadió
En MariaDB usted tiene la IFNULL función y se puede usar como
ifnull(expr1, expr2)
que dice efectivamente:
expr1 evaluar y si es nulo, a continuación, evaluar expr2
Si entiendo bien su problema, entonces su apariencia solución como
order by ifnull(vdad.vrm_document_id, ifnull(vd.timestamp_modified_utc, someothervalue)) desc
En la cláusula anterior someothervalue representa cualquier campo que es posible que desee defecto. Los criterios deseables era claro para mí. Sin embargo, si desea que el documento predeterminado para ser los primeros criterios, a continuación,
ORDER BY dv.is_default_document desc, vdad.vrm_document_id DESC, vd.timestamp_modified_utc DESC
o, si se quiere que eso sea el último de criterios, a continuación,
ORDER BY vdad.vrm_document_id DESC, vd.timestamp_modified_utc DESC, dv.is_default_document desc
EDITAR
SELECT vdad.*, vd.*
FROM `vrm_document` AS `vd`
LEFT JOIN vrm_document_active_document AS vdad ON (vd.vrm_document_id = vdad.vrm_document_id AND vd.user_id = vdad.user_id)
WHERE ((`vd`.`parent_vrm_document_id` = 1 AND `vd`.`user_id` IN (2,18,21)) OR (`vd`.`vrm_document_id` = 1 ) )
ORDER BY
CASE not exists (
SELECT 1 as cnt
FROM `vrm_document` AS `vd2`
LEFT JOIN vrm_document_active_document AS vdad2 ON (vd2.vrm_document_id = vdad2.vrm_document_id AND vd2.user_id = vdad2.user_id)
WHERE ((`vd2`.`parent_vrm_document_id` = 1 AND `vd2`.`user_id` IN (2,18,21)) OR (`vd2`.`vrm_document_id` = 1 ) )
AND not ((vdad2.vrm_document_id is null) AND (vdad2.user_id))
)
WHEN 1 THEN vd.vrm_document_id
ELSE 0 END,
vdad.vrm_document_id DESC,
vd.timestamp_modified_utc DESC
La consulta anterior usos de casos y cuando-else-end para comprobar la existencia de algunos registros. No está claro para mí lo que debería ser el criterio exacto, pero, aunque el ejemplo anterior no es su coincidencia exacta, entonces se puede sustituir
AND not ((vdad2.vrm_document_id is null) AND (vdad2.user_id))
a lo que necesita y debería funcionar.
Edit2
La consulta actual ordena por los dos criterios en la cuestión de forma predeterminada, pero si las dos primeras columnas son nulos, entonces el primer elemento será el documento predeterminado:
SELECT vdad.*, vd.*
FROM `vrm_document` AS `vd`
LEFT JOIN vrm_document_active_document AS vdad ON (vd.vrm_document_id = vdad.vrm_document_id AND vd.user_id = vdad.user_id)
WHERE ((`vd`.`parent_vrm_document_id` = 1 AND `vd`.`user_id` IN (2,18,21)) OR (`vd`.`vrm_document_id` = 1 ) )
ORDER BY
CASE not exists (
SELECT 1 as cnt
FROM `vrm_document` AS `vd2`
LEFT JOIN vrm_document_active_document AS vdad2 ON (vd2.vrm_document_id = vdad2.vrm_document_id AND vd2.user_id = vdad2.user_id)
WHERE ((`vd2`.`parent_vrm_document_id` = 1 AND `vd2`.`user_id` IN (2,18,21)) OR (`vd2`.`vrm_document_id` = 1 ) )
AND not ((vdad2.vrm_document_id is null) AND (vdad2.user_id))
)
WHEN 1 THEN vd.is_default_document
ELSE 0 END desc,
vdad.vrm_document_id DESC,
vd.timestamp_modified_utc DESC