我希望根据基于其他行的特定条件更新某些行。让我们说这个表看起来像这样:
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
可以= 1而triples
可以= 1但不能同时使用。
现在,我可以很容易地根据这些规则编写一些PHP,但我想知道是否有办法在mysql中完成所有操作?看起来我总是对从SQL语句中可以做的数量感到惊讶。
可能类似(doubles
和triples
列的两个不同陈述):
双打 - UPDATE myTable SET (doubles=1) WHERE time=time AND type=type
...但是,您将如何解释上面的规则#2(计算具有唯一类型的行数)。
这在mysql中是可行的还是PHP才是正确的方法?
提前致谢
答案 0 :(得分:1)
可以使用子选择和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`
然后,您可以将此作为stored procedure或view的基础:
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
如果群组频繁更改,则视图是更好的选择。它还确保数据consistency。如果必须运行查询以更新doubles
和triples
列,则在插入行后,数据库通常会处于不一致状态(triggers可能对此有所帮助,但是在UPDATE
中进行子选择,触发器在从正在更新的表中进行选择时出现问题。视图和查询也更容易允许其他列(例如quadruples
)而不是存储过程。
答案 1 :(得分:1)
当然,您可以在一个查询中执行此操作。使用此样本表:
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);
update语句应该加入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;