首页 > 解决方案 > 使用存在选择1获取任何列包含序列的行

问题描述

我有一个包含以下值的三列表(dbFiddle

C1      C2         C3
----------------------------
Red     Yellow     Blue
null    Red        Green
Yellow  null       Violet

我正在尝试创建一个查询,该查询返回包含值“Yellow”的所有行而不使用INor OR。如果我执行以下查询:

SELECT 1 
FROM test 
WHERE CONCAT(C1, C2, C3) LIKE '%Yellow%'

它正确返回指定的行。但是,如果我尝试在内部使用此查询exists

SELECT * 
FROM test 
WHERE EXISTS (SELECT 1 FROM test WHERE CONCAT(C1, C2, C3) LIKE '%Yellow%')

它返回所有行,而不仅仅是带有“Yellow”字样的两行。我在这里做错了什么?

任何帮助将不胜感激。

标签: sqlsql-server

解决方案


关于

SELECT 1 FROM test WHERE CONCAT(C1, C2, C3) LIKE '%Yellow%'

“正确返回指定的行”

选择返回单列,1,尽管这是因为有一行包含Yellow其文本中某处的一列。

这是因为存在

如果子查询包含任何行,则返回 TRUE。

即以下所有查询还返回了test表中的所有行:

SELECT * FROM test WHERE EXISTS (SELECT 1);

SELECT * FROM test WHERE EXISTS (SELECT 0);

SELECT * FROM test WHERE EXISTS (SELECT NULL);

...仅仅因为SELECT返回至少一行!

的通常用法EXISTS还包括将EXISTS后面的子查询关联到外部选择。

相关示例

在下面的例子中,我们有 4 个人住在两栋房子里。在这里,我们EXISTS用来找出快乐的人的名字,并且还有其他人也快乐地住在同一个(相关的)房子里。

CREATE TABLE House
(
    HouseId INT PRIMARY KEY,
    Name VARCHAR(MAX)
);

CREATE TABLE Person
(
    PersonId INT PRIMARY KEY,
    HouseId INT FOREIGN KEY REFERENCES HOUSE(HouseId),
    Name VARCHAR(MAX),
    IsHappy BIT
);

INSERT INTO House(HouseId, Name) VALUES (1, 'House1'), (2, 'House2');

INSERT INTO Person(PersonId, HouseId, Name, IsHappy) VALUES 
(1, 1, 'Joe', 0), 
(2, 1, 'Jim', 1),
(3, 2, 'Fred', 1),
(4, 2, 'Mary', 1);

SELECT pOuter.Name
FROM Person pOuter
WHERE pOuter.IsHappy = 1
AND EXISTS 
    (SELECT 1 
        FROM Person pInner 
        WHERE pInner.HouseId = pOuter.HouseId 
        AND pInner.PersonId != pOuter.PersonId
        AND pInner.IsHappy = 1);

退货

Mary
Fred

(显然还有其他方法可以找到相同的结果,例如在存在 2 个或更多快乐的人的情况下找到 House Id 的分组等)


推荐阅读