mysql - ОБНОВЛЕНИЕ строки, основанной на других строках - PullRequest
0 голосов
/ 05 февраля 2011

Я хочу обновить определенные строки на основе определенных критериев на основе других строк.Допустим, таблица выглядит следующим образом:

COLUMNS:   time              type     genre    doubles     triples
ROW 1:    2010.06.21 12:00    1        1        0            0
ROW 2:    2010.06.21 12:00    1        2        0            0
ROW 3:    2010.06.21 12:00    1        1        0            0
ROW 4:    2010.06.21 12:00    2        3        0            0
ROW 5:    2010.06.22 12:00    2        2        0            0
ROW 6:    2010.06.22 12:00    2        3        0            0
ROW 7:    2010.06.22 12:00    1        1        0            0

Я хочу обновить столбцы doubles и triples на основе следующих правил:

1) Искать только для обновлениястроки, где time=time и type=type между строками (например, строки 1,2,3 и строки 5 и 6).

2) Затем подсчитайте количество # genre между этими строками и, если есть два разных genres, измените столбец doubles на 1, или, если их три, измените triples от столбца до 1. Так, например, в приведенной выше таблице строки 1,2,3 будут иметь doubles=1, потому что между тремя строками есть два разных жанра.Ряды 5 и 6 также будут иметь doubles=1, потому что между строками снова есть два разных жанра.Doubles can = 1 и triples can = 1, но не оба одновременно.

Теперь я мог бы написать довольно немного PHP на основе этих правил, я думаю, но мне интересно, есть ли способсделать все это в MySQL?Кажется, я всегда удивляюсь тому, сколько вы можете сделать из оператора SQL.

Может быть что-то вроде (два разных оператора для столбца doubles и triples):

Удваивается- UPDATE myTable SET (doubles=1) WHERE time=time AND type=type ... но как бы вы объяснили вышеприведенное правило № 2 (считая количество строк с уникальными жанрами).

Возможно ли это в mysql или PHP - верный путь?

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 05 февраля 2011

Конечно, вы можете сделать это одним запросом. Используя этот образец таблицы:

create table duotri (time varchar(100), type int, genre int, doubles int, triples int);
insert duotri values
('2010.06.21 12:00'    ,1        ,1        ,0            ,0),
('2010.06.21 12:00'    ,1        ,2        ,0            ,0),
('2010.06.21 12:00'    ,1        ,1        ,0            ,0),
('2010.06.21 12:00'    ,2        ,3        ,0            ,0),
('2010.06.22 12:00'    ,2        ,2        ,0            ,0),
('2010.06.22 12:00'    ,2        ,3        ,0            ,0),
('2010.06.22 12:00'    ,1        ,1        ,0            ,0);

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

update duotri t1
inner join (
    select time, type,
     case when count(distinct genre) = 2 then 1 else 0 end doubles,
     case when count(distinct genre) = 3 then 1 else 0 end triples
    from duotri
    group by time, type) t2
   on t1.time=t2.time and t1.type=t2.type
set t1.doubles=t2.doubles, t1.triples = t2.triples;
1 голос
/ 05 февраля 2011

Это может быть возможно с помощью подвыборов и выражения CASE или путем сравнения счетчика с счетчиком для столбца, но это будет сложно из-за того, что MySQL не позволяет выбрать таблицу, которая используетсяОбновлено в подразделе.

Вы можете легко сделать это в выделенном списке (я даю таблице название «записи», так как вы не указали ее; предоставление примеров в SQL, а не в предварительно отформатированном тексте всегда полезно):

SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`,
     COUNT(DISTINCT r1.genre) = 2 AS doubles,
     COUNT(DISTINCT r1.genre) = 3 AS triples
  FROM recordings AS r0
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type`
  GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre`

Затем вы можете использовать это в качестве основы для хранимой процедуры или представления :

ALTER TABLE recordings DROP COLUMN doubles;
ALTER TABLE recordings DROP COLUMN triples;
ALTER TABLE recordings ADD id INT PRIMARY KEY AUTO_INCREMENT;

CREATE VIEW recording_genre_count AS
SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`,
     CASE COUNT(DISTINCT r1.genre) WHEN 2 THEN 1 ELSE 0 END AS doubles,
     CASE COUNT(DISTINCT r1.genre) WHEN 3 THEN 1 ELSE 0 END AS triples
  FROM recordings AS r0
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type`
  GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre`;
  --Since the columns of recordings are functionally dependent on recordings.id,
  --you could use just "GROUP BY r0.id", but the above will work on other
  -- DBMSs

Если группы часто меняются,вид - лучший выбор.Это также обеспечивает согласованность данных .Если вам нужно выполнить запрос для обновления столбцов doubles и triples, БД часто будет в несовместимом состоянии сразу после вставки строк ( триггеры могут помочь с этим, но, как и в случае свыбирается в UPDATE с, триггеры испытывают проблемы при выборе из обновляемой таблицы).Представления и запросы также более легко допускают дополнительные столбцы (например, quadruples), чем хранимая процедура.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...