首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQL :如何选择某些属性为null的记录

SQL :如何选择某些属性为null的记录
EN

Stack Overflow用户
提问于 2021-12-16 10:37:34
回答 3查看 118关注 0票数 0

我使用Server 2014数据库和创建和运行查询。

表格如下:

代码语言:javascript
运行
复制
Persons

| ID | personName |
+----+------------+
| 1  |    Hamish  |
| 2  |    Morag   |
| 3  |    Ewan    |

Cars

| ID | CarName |
+----+---------+
| 1  |  Humber |
| 2  |  Austen |
| 3  |  Morris |

Gadgets

| ID | GadgetName |
+----+------------+
| 1  |  Cassette  |
| 2  |     CD     |
| 3  |   Radio    |

CarToPersonMap

| ID | CarID | PersonID |
+----+-------+----------+
| 1  |   1   |    1     |
| 2  |   2   |    1     |
| 3  |   3   |    2     |

CarToGadgetMap

| ID | CarID | GadgetID |
+----+-------+----------+
| 1  |   2   |    2     |

映射表有适当的外键。

我想找那些有车的人,但没有一辆车有小玩意。所以在上面的例子中,我想找到莫拉格,他有一辆没有小玩意的车。哈米什有两辆车,但其中一辆车有一个小工具,所以我不想让ResultSet包括哈米什。

EN

回答 3

Stack Overflow用户

发布于 2021-12-16 12:04:41

我会用几个CTE:

代码语言:javascript
运行
复制
With CarGadgetCount AS (
         SELECT c.ID as CarID, 
                SUM(CASE cg.ID IS NOT NULL THEN 1 ELSE 0 END) AS GadgetCount
         FROM Car c 
              LEFT JOIN CarToGadgetMap cg
                        ON cg.CarID = c.ID
         GROUP BY c.ID
    ),
    PersonCarCount AS (
         SELECT p.ID as PersonID, 
                SUM(CASE cp.ID IS NOT NULL THEN 1 ELSE 0 END) AS CarCount
         FROM Person p 
              LEFT JOIN CarToPersonMap cp
                        ON cp.PersonID = p.ID
    )
    PersonGadgetCount AS (
         SELECT p.ID AS PersonID,
                SUM(CASE WHEN cg.GadgetCount IS NULL THEN 0 ELSE cg.GadgetCount END) as GadgetCount
         FROM Person p
              LEFT JOIN CarToPersonMap cp
                        ON cp.PersonID = p.ID
              LEFT JOIN CarGadgetCount cg 
                         ON cg.CarID = cp.CarID
         GROUP BY p.ID
    )
SELECT p.personName 
FROM Person p
     INNER JOIN PersonGadgetCount pg
                ON pg.PersonID = p.ID
     INNER JOIN PersonCarCount pc 
                ON pc.PersonID = p.ID
WHERE pc.CarCount > 0
      AND pg.GadgetCount = 0;

这样,如果您想实际查看谁有汽车和谁有小工具,那么可以在select中切换WHERE子句和指定的列。

票数 0
EN

Stack Overflow用户

发布于 2021-12-16 14:00:30

您也可以使用EXISTS获得预期的输出。查询将类似于,

代码语言:javascript
运行
复制
SELECT DISTINCT personName
FROM Persons p 
WHERE 
    EXISTS ( SELECT 1 FROM CarToPersonMap WHERE  personId = p.ID )
    AND NOT EXISTS ( SELECT 1 
            FROM CarToGadgetMap cgm 
            JOIN CarToPersonMap cpm ON cpm.personId = p.ID AND cpm.carId = cgm.carId)

这里是小提琴

票数 0
EN

Stack Overflow用户

发布于 2021-12-16 14:55:46

您可以在EXISTS中进行条件聚合。

代码语言:javascript
运行
复制
SELECT personName
FROM Persons p 
WHERE EXISTS (SELECT 1
    FROM CarToPersonMap cpm
    LEFT JOIN CarToGadgetMap cgm ON cpm.carId = cgm.carID
    WHERE cpm.personId = p.ID
    HAVING COUNT(cgm.carID) = 0
);

上面写的是:

  • 获取子查询中有行的所有Persons
  • 该子查询是它们的所有CarToPersonMap,与相关的CarToGadgetMap一起使用。
  • 必须没有具有匹配的CarToGadgetMap值的行(因为COUNT只计算非空值)。

db<>fiddle

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70377549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档