[英]SQL: is there a single query to get "all rows with X, or if none, all rows with Y"?
我想知道如何获得“col='X'的所有行;如果没有,col='Y'的所有行”
简化的数据库;
CREATE TABLE CHARACTER_NAMES(CHARACTER_ID, LANG VARCHAR(3), NAME);
INSERT INTO CHARACTER_NAMES(1, "ENG", "DONALD DUCK");
INSERT INTO CHARACTER_NAMES(1, "ENG", "GOOD OL' DONALD");
INSERT INTO CHARACTER_NAMES(1, "SWE", "KALLE ANKA");
INSERT INTO CHARACTER_NAMES(1, "SWE", "KALLEN");
INSERT INTO CHARACTER_NAMES(2, "ENG", "MICKEY MOUSE");
INSERT INTO CHARACTER_NAMES(2, "SWE", "MUSSE PIGG");
INSERT INTO CHARACTER_NAMES(2, "SWE", "MUSEN");
INSERT INTO CHARACTER_NAMES(3, "ENG", "GOOFY");
INSERT INTO CHARACTER_NAMES(3, "NOR", "FEDTMULE");
(字符在同一种语言中具有多个名称有点强迫,但这就是真实数据库的样子。另外,“CHARACTER_ID”也是 CHARACTER 表的外键,但这不是问题的一部分,因此省略.)
用户有语言设置,当数据库查询特定字符时,查询应返回所选语言的名称,如果所选语言没有结果,则返回英文名称。 在上面的示例中,如果设置为“瑞典语”并且用户选择了字符 3(高飞),则名称搜索应返回“高飞”,因为没有注册瑞典名称。 如果用户选择了 Mickey Mouse,搜索应该返回 2 行:“Musse Pigg”和“Musen”。
我想知道这是否可以在 SQL 查询中表达。
如果我只想要所选语言的 FIRST,如果没有,我可以使用:
SELECT NAME FROM CHARACTER_NAMES
WHERE CHARACTER_ID=?
ORDER BY CASE
WHEN LANG='NOR' THEN 1
WHEN LANG='ENG' THEN 2
END
LIMIT 1;
但是由于我不知道所选语言中会有多少个名字,所以我必须让这个 LIMIT 有所不同,而且我真的不知道如何以一种好的和适当的方式做到这一点。
我想知道如何获得“col='X'的所有行;如果没有,col='Y'的所有行”
SELECT *
FROM table
WHERE col='X'
UNION ALL
SELECT *
FROM table
WHERE col='Y'
AND NOT EXISTS ( SELECT NULL
FROM table
WHERE col='X' )
如果存在col='X'
的行,则 WHERE EXISTS 将给出 FALSE,第二个子查询将不返回任何内容 - 即仅返回第一个子查询的 output。
向后,如果没有col='X'
行,那么第一个子查询将不会返回行,但 WHERE EXISTS 将给出 TRUE,第二个子查询将返回col='Y'
所有行 - 即仅 output 的第二个子查询将被退回。
或者你可以使用
SELECT *
FROM table
WHERE col = CASE WHEN EXISTS ( SELECT NULL
FROM table
WHERE col='X' )
THEN 'X'
ELSE 'Y'
END;
当然还有更多的变种...
在 MySQL 8 中,您可以使用带有RANK
的CASE
表达式来获得所需的结果:
WITH cte AS (
SELECT *, RANK() OVER (PARTITION BY character_id ORDER BY CASE
WHEN lang = 'NOR' THEN 1
WHEN lang = 'ENG' THEN 2
ELSE 3
END) AS rnk
FROM character_names
)
SELECT *
FROM cte
WHERE rnk = 1
使用NOT EXISTS
可以获得相同的结果:
SELECT *
FROM character_names AS t1
WHERE lang = 'NOR'
OR lang = 'ENG' AND NOT EXISTS (
SELECT *
FROM character_names AS t2
WHERE t2.character_id = t1.character_id
AND t2.lang = 'NOR'
)
结果:
character_id | 郎 | 姓名 | rnk |
---|---|---|---|
1 | 英文 | 唐老鸭 | 1 |
1 | 英文 | 好老唐纳德 | 1 |
2 | 英文 | 米老鼠 | 1 |
3 | 也不 | FEDTMULE | 1 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.