我有一个包含两个表,song和edited_song的数据库模式。除了edit_song中名为deleted的一个额外列之外,这些表是相同的。 edited_song-table包含对歌曲表中id的引用。我想找到所有没有被删除的歌曲。
我有一个UNION语句,其中I GROUP是两个SELECT语句的结果的id。我想排除已删除列的值为1的结果。可以在此处看到设置示例。
CREATE TABLE if not exists song
(
id int(11) NOT NULL auto_increment ,
title varchar(255),
PRIMARY KEY (id)
);
CREATE TABLE if not exists editedsong
(
id int(11) NOT NULL auto_increment ,
title varchar(255),
deleted tinyint(1),
PRIMARY KEY (id)
);
INSERT INTO song (id, title) VALUES
(1, 'Born in the USA');
INSERT INTO editedsong (id, title, deleted) VALUES
(1, 'Born in the USA', 1);
查询在这里:
SELECT * FROM
((SELECT *, 0 AS deleted FROM song WHERE id=1)
UNION
(SELECT * FROM editedsong WHERE id=1)) AS song
WHERE song.deleted!=1
GROUP BY song.id
使用UNION语句而不是连接,因为这两个表中有大量文本,并且连接导致写入磁盘。这是真实查询的简化形式,但它再现了我遇到的问题。我希望查询不会产生任何结果,因为GROUP BY应保留第一行并丢弃所有后续内容。为什么不这样做?是因为WHERE在GROUP BY之前执行了吗?如果是,那么克服这个问题的好方法是什么?
答案 0 :(得分:0)
SQLFiddle中的代码不起作用的原因是WHERE
子句在GROUP BY
执行之前从editsong中排除了已删除的记录。
您可以使用HAVING
在GROUP BY
子句后应用条件。
这似乎有效:
SELECT *, max(deleted) as md FROM
((SELECT *, 0 AS deleted FROM song)
UNION
(SELECT * FROM editedsong)) AS song
-- WHERE song.deleted!=1
GROUP BY song.id
HAVING md != 1
这将返回song
的记录,而不是editedsong
的记录,用于尚未删除的记录。如果您想要另一个,请颠倒UNION
子句中项目的顺序。
GROUP BY
的这种语法很不寻常,我很惊讶它得到了支持。我使用的大多数数据库系统都要求输出中的每个字段指定一些处理(MAX
,COUNT
,GROUP BY
等)。因此SELECT *
与GROUP BY
不兼容。 MySQL必须在这里做出一些假设或者有一些默认行为,但我认为大多数服务器都不喜欢它(我也是)。