2016-05-27 2 views
4

Примеры данныхMySQL - обновление таблицы с номером строки в группе

id | order_id | instalment_num | date_due 
--------------------------------------------------------- 
1 | 10000  | 1    | 2010-07-09 00:00:00 
2 | 10000  | 1    | 2010-09-06 11:39:56 
3 | 10001  | 1    | 2014-04-25 15:46:52 
4 | 10002  | 1    | 2010-01-11 00:00:00 
5 | 10003  | 1    | 2010-01-04 00:00:00 
6 | 10003  | 1    | 2016-05-31 00:00:00 
7 | 10003  | 1    | 2010-01-08 00:00:00 
8 | 10003  | 1    | 2010-01-06 09:06:26 
9 | 10004  | 1    | 2010-01-11 11:25:07 
10 | 10004  | 1    | 2010-01-12 07:06:42 

желаемого результата

id | order_id | instalment_num | date_due 
--------------------------------------------------------- 
1 | 10000  | 1    | 2010-07-09 00:00:00 
2 | 10000  | 2    | 2010-09-06 11:39:56 
3 | 10001  | 1    | 2014-04-25 15:46:52 
4 | 10002  | 1    | 2010-01-11 00:00:00 
5 | 10003  | 1    | 2010-01-04 00:00:00 
8 | 10003  | 2    | 2010-01-06 09:06:26 
7 | 10003  | 3    | 2010-01-08 00:00:00 
6 | 10003  | 4    | 2016-05-31 00:00:00 
9 | 10004  | 1    | 2010-01-11 11:25:07 
10 | 10004  | 2    | 2010-01-12 07:06:42 

Как вы можете видеть, у меня есть instalment_num столбец, который должен показать номер/индекс каждой строки, принадлежащей order_id, определяемый порядком date_due ASC, id ASC.

Как я могу обновить колонку instalment_num?

Дополнительные примечания

  • date_due колонка не является уникальным, и может быть много id s или order_id s с точно такой же отметкой времени.

  • Если временная метка одинакова для двух рядов, принадлежащих тому же order_id, она должна заказать их на id в качестве резервной копии.

  • Мне нужен запрос, который обновит этот столбец.

+0

Что вы попробовали? –

+0

Может ли быть какая-то повторяющаяся команда order_id/date_due? – jarlh

+0

@jarlh Да, и тогда это должно быть 'date_due ASC, id ASC'. – BadHorsie

ответ

4

Это, как я хотел бы сделать это:

SELECT a.id, 
    a.order_id, 
    COUNT(b.id)+1 AS instalment_num, 
    a.date_due 
FROM sample_data a 
    LEFT JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id)) 
GROUP BY a.id, a.order_id, a.date_due 
ORDER BY a.order_id, a.date_due, a.id 

UPDATE версии попытка:

UPDATE sample_data 
    LEFT JOIN (SELECT a.id, 
    COUNT(b.id)+1 AS instalment_num 
FROM sample_data a 
    JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id)) 
GROUP BY a.id) c ON c.id=sample_data.id 
SET sample_data.instalment_num=c.instalment_num 
+0

Не быстро, но он работает. Как мне превратить это в ОБНОВЛЕНИЕ? – BadHorsie

+0

Согласен. Это не самый быстрый способ сделать это, но это довольно чисто и легко понять. Работа над обновлением ... дайте мне минуту ... – SunKnight0

+0

Я пробовал, но получаю 'Вы не можете указать целевую таблицу для обновления в FROM clause'. +1 для удобства понимания. – BadHorsie

1

Вы пытаетесь достичь того, что ROW_NUMBER с разделом будет работать с использованием чего-то вроде SQL Server или Oracle. Вы можете смоделировать с помощью запроса вывоза мебели:

SELECT t.id, t.order_id, 
(
    SELECT 1 + COUNT(*) 
    FROM sampleData 
    WHERE (date_due < t.date_due OR (date_due = t.date_due AND id < t.id)) AND 
     order_id = t.order_id 
) AS instalment_num, 
    t.date_due 
FROM sampleData t 
ORDER BY t.order_id, t.date_due 

Этот запрос будет заказать instalment_num по due_date в порядке возрастания. А в случае галстука в due_date, он будет заказывать по id в порядке возрастания.

Перейдите по ссылке ниже для демо:

SQLFiddle

+0

Я собирался написать тот же ответ, но он столкнется с проблемами, если появится дубликат order_id/date_due. – jarlh

+0

Спасибо. Учитывает ли это резерв при заказе по идентификатору, если 'date_due' одинаково для двух строк в одной группе' order_id'? – BadHorsie

+0

@jarlh Если бы заказы на записи в подзапросе приводили порядок 'id' в случае привязки к отметкам времени? Документация, похоже, говорит, что MySQL выполнит заказ (хотя MariaDB этого не делает). –

0
select 
    sub.order_id, sub.date_due, 
    @group_rn:= case 
       when @group_order_id=sub.order_id then @group_rn:[email protected]_rn:+1 
       else 1 
       end as instalment_num, 
    @group_order_id:=sub.order_id 
FROM (select @group_rn:=0, group_order_id=0) init, 
    (select * 
     from the_table 
     order by order_id, date_due) sub 
1

Для нумерации для начала 1:

UPDATE sample_data 
    LEFT JOIN (SELECT a.id, 
    COUNT(b.id) AS instalment_num 
FROM sample_data a 
    JOIN sample_data b ON a.order_id = b.order_id AND (a.date_due > b.date_due OR (a.date_due=b.date_due AND a.id + 1 > b.id)) 
GROUP BY a.id) c ON c.id = sample_data.id 
SET sample_data.instalment_num = c.instalment_num 
Смежные вопросы