我有一个动物园,每个动物园有很多笼子,每个笼子有很多动物。
动物园:
+----+
| 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]
我感觉自己丢失了一些东西,应该可以使用更简单的语句来运行此查询。
答案 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;