2012-06-11 2 views
5

есть таблица фотографиязапроса для добавления добавочного поля на основе GROUP BY

photos.id 
photos.user_id 
photos.order 

А) Можно ли с помощью одного запроса к группе всех фотографиям пользователя, а затем обновить заказ 1,2,3 .. N?

B) добавлено завихрение, что, если некоторые из фотографий уже имеют отношение к порядку? Удостоверьтесь, что новый файл photos.order никогда не повторяется и заполняет заказы муравьями ниже или выше существующих (как можно лучше)

Моя единственная мысль - просто запустить сценарий на этом и пропустить его, порядок "все?

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

Сейчас данные могут выглядеть следующим образом

user_id = 1 
photo_id = 1 
order = NULL 

user_id = 2 
photo_id = 2 
order = NULL 

user_id = 1 
photo_id = 3 
order = NULL 

желаемый результат будет

user_id = 1 
photo_id = 1 
order = 1 

user_id = 2 
photo_id = 2 
order = 1 

user_id = 1 
photo_id = 3 
order = 2 

ответ

11

A)

Вы можете использовать переменную, который увеличивает с каждым строка и сбрасывается с каждым user_ID, чтобы получить количество строк.

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)

Мой Первое решение было просто добавить Order к перебору, который добавляет номер строки, поэтому ничего с Order получает отсортированный по его поручению первым, но это работает только в том случае, если ваша система заказа не имеет зазоров и начинается с 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

ЗАКАЗА с зазорами

я в конце концов нашел способ поддержания порядка сортировки, даже когда есть пробелы в последовательности.

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` 

Однако, как вы можете видеть, это довольно сложно. Это работает, обрабатывая значения order отдельно для тех, у кого нет. Верхний запрос просто оценивает все фотографии без значения order в порядке идентификатора для каждого пользователя. В нижнем запросе используется кросс-соединение для создания последовательного списка от 1 до n для каждого идентификатора пользователя (до количества записей для каждого User_ID).Таким образом, с набором данных, как это:

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 

Он будет генерировать

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

Затем он использует NOT EXISTS для elimiate всех комбинаций уже используемых фотографий с не нулевой order и ранжированы в порядке RowNum секционированной от User_ID давая

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

значение RowNum2 затем могут быть сопоставлены со значением RowNum, достигнутый в подзапросу из, давая правильное значение order. Долго наматывается, но он работает.

Example on SQL Fiddle

+0

в-долбанные-напряжены .. спасибо за это ... Я думаю, что для моего здравомыслия я могу просто скрипт на это через код !!! – cgmckeever

+0

Да, я бы тоже пошел на этот вариант, но моя упрямство означала, как только я начал, я должен был найти решение! – GarethD

+0

LOL - да. Я знаю, что вы имеете в виду. Я делал это во многих случаях. Но для этого я думаю, что прямолинейный цикл цикла, в который я могу добавить некоторую пользовательскую логику, чтобы приблизиться к parallel MUCH оценили! – cgmckeever

Смежные вопросы