繁体   English   中英

SQL:是否有一个查询来获取“所有带有 X 的行,或者如果没有,所有带有 Y 的行”?

[英]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 中,您可以使用带有RANKCASE表达式来获得所需的结果:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM