2012-06-11 13 views
5

tener una mesa de fotosconsulta para agregar campo gradual a partir GROUP BY

photos.id 
photos.user_id 
photos.order 

a) ¿Es posible a través de una sola consulta para agrupar todas las fotos de un usuario y luego actualizar el orden 1,2,3 .. N?

B) giro adicional, ¿qué pasa si algunas de las fotos ya tienen un valor de orden asociado? Asegúrate de que las nuevas fotos.orden nunca se repitan y llene pedidos más bajos o más altos que los existentes (lo mejor posible)

Mi único pensamiento es solo ejecutar un script sobre esto y recorrerlo y volver a ' ordenar 'todo?

photos.id int(10) 
photos.created_at datetime 
photos.order int(10) 
photos.user_id int(10) 

En este momento los datos puede tener este aspecto

user_id = 1 
photo_id = 1 
order = NULL 

user_id = 2 
photo_id = 2 
order = NULL 

user_id = 1 
photo_id = 3 
order = NULL 

el resultado deseado sería

user_id = 1 
photo_id = 1 
order = 1 

user_id = 2 
photo_id = 2 
order = 1 

user_id = 1 
photo_id = 3 
order = 2 

Respuesta

11

A)

Puede utilizar una variable que se incrementa con cada uno remar y reiniciar con cada user_ID para obtener el recuento de filas.

SELECT ID, 
     User_ID, 
     `Order` 
FROM ( SELECT @r:= IF(@u = User_ID, @r + 1,1) AS `Order`, 
        ID, 
        User_ID, 
        @u:= User_ID 
      FROM Photos, 
        (SELECT @r:= 1) AS r, 
        (SELECT @u:= 0) AS u 
      ORDER BY User_ID, ID 
     ) AS Photos 

Example on SQL Fiddle

B)

Mi primera solución era simplemente añadir Order a la clasificación que se suma el número de fila, por lo tanto, cualquier cosa con un Order Obtiene ordenadas según su orden primero, pero esto solo funciona si su sistema de pedidos no tiene espacios vacíos y comienza en 1:

SELECT ID, 
     User_ID, 
     RowNumber AS `Order` 
FROM ( SELECT @r:= IF(@u = User_ID, @r + 1,1) AS `RowNumber`, 
        ID, 
        User_ID, 
        @u:= User_ID 
      FROM Photos, 
        (SELECT @i:= 1) AS r, 
        (SELECT @u:= 0) AS u 
      ORDER BY User_ID, `Order`, ID 
     ) AS Photos 
ORDER BY `User_ID`, `Order` 

Example using Order Field

PEDIDO con huecos

he encontrado finalmente una forma de mantener el orden, incluso cuando hay lagunas en la secuencia.

SELECT ID, User_ID, `Order` 
FROM Photos 
WHERE `Order` IS NOT NULL 
UNION ALL 
SELECT Photos.ID, 
     Photos.user_ID, 
     Numbers.RowNum 
FROM ( SELECT ID, 
        User_ID, 
        @r1:= IF(@u1 = User_ID,@r1 + 1,1) AS RowNum, 
        @u1:= User_ID 
      FROM Photos, 
        (SELECT @r1:= 0) AS r, 
        (SELECT @u1:= 0) AS u 
      WHERE `Order` IS NULL 
      ORDER BY User_ID, ID 
     ) AS Photos 
     INNER JOIN 
     ( SELECT User_ID, 
        RowNum, 
        @r2:= IF(@u2 = User_ID,@r2 + 1,1) AS RowNum2, 
        @u2:= User_ID 
      FROM ( SELECT DISTINCT p.User_ID, o.RowNum 
         FROM Photos AS p, 
           ( SELECT @i:= @i + 1 AS RowNum 
            FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY, 
              (SELECT @i:= 0) AS i 
           ) AS o 
         WHERE RowNum <= (SELECT COUNT(*) FROM Photos P1 WHERE p.User_ID = p1.User_ID) 
         AND  NOT EXISTS 
           ( SELECT 1 
            FROM Photos p2 
            WHERE p.User_ID = p2.User_ID 
            AND  o.RowNum = p2.`Order` 
           ) 
         AND  p.`Order` IS NULL 
         ORDER BY User_ID, RowNum 
        ) AS p, 
        (SELECT @r2:= 0) AS r, 
        (SELECT @u2:= 0) AS u 
      ORDER BY user_ID, RowNum 
     ) AS numbers 
      ON Photos.User_ID = numbers.User_ID 
      AND photos.RowNum = numbers.RowNum2 
ORDER BY User_ID, `Order` 

Sin embargo, como puede ver, esto es bastante complicado. Esto funciona tratando a aquellos con un valor de order por separado a los que no tienen. La consulta principal solo clasifica todas las fotos sin order valor en orden de ID para cada usuario. La consulta inferior utiliza una combinación cruzada para generar una lista secuencial de 1 a n para cada ID de usuario (hasta el número de entradas para cada ID de usuario).Así que con un conjunto de datos de la siguiente manera:

ID User_ID Order 
1 1  NULL 
2 2  NULL 
3 1  NULL 
4 1  1 
5 1  3 
6 2  2 
7 2  3 

generaría

UserID RowNum 
1  1 
1  2 
1  3 
1  4 
2  1 
2  2 
2  3 

A continuación, utiliza NOT EXISTS a elimiate todas las combinaciones ya utilizadas por las fotos con un no nulo order y está clasificada con el fin de ROWNUM particionado por ID_Usuario dando

UserID RowNum Rownum2 
1  2  1 
1  4  2 
2  1  1 

el valor RowNum2 entonces se puede emparejar con el valor rownum logrado en el de subconsulta, dando el valor correcto order. De largo aliento, pero funciona.

Example on SQL Fiddle

+0

en volviendo loco-tensa .. gracias por esto ... Creo que para mi cordura se me permite la escritura simplemente esto a través de código !!! – cgmckeever

+0

Sí, también me hubiera optado por esa opción, pero mi terquedad significaba que una vez que comencé tuve que encontrar una solución. – GarethD

+0

LOL - sí - Sé lo que quieres decir ... Lo he hecho en muchas ocasiones ... pero para este, creo que un ciclo de iteración recto en el que puedo agregar algo de lógica personalizada para acercar lo más posible paralelo MUCHO apreciado! – cgmckeever