SQL连接多个表,获取某些行的计数,并检查某些行是否满足条件

时间:2020-08-14 20:05:25

标签: sql sql-server

我有一个动物园,每个动物园有很多笼子,每个笼子有很多动物。

动物园:

+----+
| Id |
+----+
|  1 |
|  2 |
+----+

笼:

+----+-------+
| Id | ZooId |
+----+-------+
|  1 |     1 |
|  2 |     1 |
|  3 |     2 |
|  4 |     2 |
|  5 |     2 |
+----+-------+

动物:

+----+--------+----------+
| Id | CageId | IsHungry |
+----+--------+----------+
|  1 |      1 |        0 |
|  2 |      1 |        0 |
|  3 |      1 |        0 |
|  4 |      2 |        1 |
|  5 |      3 |        0 |
|  6 |      4 |        0 |
|  7 |      5 |        0 |
+----+--------+----------+

我正在尝试设计一个查询,以显示每个动物园,该动物园的笼子数量以及该动物园是否有饥饿的动物。

这是我期望的结果:

+-------+-----------+--------------+
| ZooID | CageCount | AnyoneHungry |
+-------+-----------+--------------+
|     1 |         2 |            1 |
|     2 |         3 |            0 |
+-------+-----------+--------------+

我可以得到一个动物园中的笼子数量:

SELECT 
    [c].[ZooId],
    COUNT(*) AS [NumCages]
FROM [Cage] [c]
GROUP BY [c].[ZooId]
ORDER BY [NumCages] DESC

我可以确定笼子里是否有饥饿的动物:

SELECT CASE WHEN EXISTS (
    SELECT NULL
    FROM [Animal] [a]
    WHERE [a].[CageId] = @CageId AND [a].[IsHungry] = 1
) THEN 1 ELSE 0 END

但是我很难将两者结合成一个有效运行的查询(在这种情况下,动物园非常受欢迎,有数以百万计的笼子和动物)。

SELECT 
    [c].[ZooId], 
    COUNT(*) AS [CageCount], 
    MAX(CONVERT(INT, [x].[AnyoneHungry])) AS [AnyoneHungry]
FROM [Cage] [c]
INNER JOIN  (
    SELECT [a].[CageId], MAX(CONVERT(INT, [a].[IsHungry])) AS [AnyoneHungry]
    FROM [Animal] [a]
    GROUP BY [a].[CageId]
) [x] on [x].[CageId] = [c].[Id]
GROUP BY [c].[ZooId]

我感觉自己丢失了一些东西,应该可以使用更简单的语句来运行此查询。

2 个答案:

答案 0 :(得分:3)

这应该做

SELECT
    Z.Id,
    COUNT(DISTINCT C.Id) AS CageCount,
    COALESCE(MAX(CAST(A.IsHungry AS INT)), 0) AS AnyHungry /*The cast is only required if A.IsHungry is BIT and not INT*/
FROM Zoo Z
    LEFT JOIN Cage C ON Z.Id = C.ZooId
    LEFT JOIN Animal A ON C.Id = A.CageId
GROUP BY Z.Id

答案 1 :(得分:2)

如果您只需要动物园身份证和饥饿的动物:

SELECT c.zooid,
       COUNT(DISTINCT C.Id) as CageCount,
       COALESCE(MAX(CONVERT(int, a.IsHungry)), 0) AS AnyHungry
FROM Cage C LEFT JOIN
     Animal A
     ON c.Id = a.CageId AND a.IsHungry = 1
GROUP BY c.zooid;