我有这三个表:
table_things: [id]
table_location: [id]
[location]
[quantity]
table_reservation: [id]
[quantity]
[location]
[list_id]
示例数据:
table_things:
id
1
2
3
table_location
id location quantity
1 100 10
1 101 4
2 100 1
table_reservation
id quantity location list_id
1 2 100 500
1 1 100 0
2 1 100 0
它们通过[id]在所有三个表中相同,并且[location]在table_loation和table_reservation中是相同的。
table_location中的[quantity]显示某个地方([location])有多少([数量])事物([id])。
table_reservation中的[quantity]显示在某个地方([location])保留了多少([数量])事物([id])。
table_reservation中有0行或多行对应table_location.id = table_reservation_id,所以我可能需要使用外连接。
我想创建一个回答问题的查询:在这个特定的地方有多少东西([id])(WHERE table_location = 123),保留了多少这些东西(table_reservation。[quantity])和保留的数量有多少在table_reservation.list_id上,其中table_reservation.list_id> 0
我无法将聚合函数直接应用于答案仅包含table_location中具有给定WHERE子句的行数,同时我得到正确数量的table_reservation.quantity。
如果我这样做,我会在答案中得到正确的行数:
SELECT table_things.[id],
table_location.[quantity],
SUM(table_reservation.[quantity]
FROM table_location
INNER JOIN table_things ON table_location.[id] = table_things.[id]
RIGHT OUTER JOIN table_reservation ON table_things.location = table_reservation.location
WHERE table_location.location = 100
GROUP BY table_things.[id], table_location[quantity]
但该查询的问题是我(当然)得到一个不正确的SUM值(table_reservation。[quantity]),因为它总结了table_reservation中的所有相应行,并在每个行上发布相同的值结果。
第二部分是尝试获得table_reservation数量的正确值。[quantity]其list_id>我在SELECT列表中尝试了类似的东西:
(SELECT SUM(CASE WHEN table_reservation.list_id > 0 THEN table_reservation.[quantity] ELSE 0 END)) AS test
但这甚至都没有解析......我只是表现出来表达我的想法。
可能是一个简单的SQL问题,但是自从我做这些复杂的查询以来已经太久了。
答案 0 :(得分:1)
前两个问题:
在这个特定的地方有多少东西([id])(WHERE table_location = 123),保留了多少这些东西(table_reservation。[quantity])
我认为您只需要LEFT OUTER JOIN
代替RIGHT
,并为table_reservation
SELECT l.id,
l.quantity,
Reserved = SUM(ISNULL(r.quantity, 0))
FROM table_location AS l
INNER JOIN table_things AS t
ON t.id = l.ID
LEFT JOIN table_reservation r
ON r.id = t.id
AND r.location = l.location
WHERE l.location = 100
GROUP BY l.id, l.quantity;
N.B我添加了ISNULL
,这样当没有任何保留时,你会得到0而不是NULL
的结果。您根本不需要引用table_things
,但我猜这是一个简化的示例,您可能需要其他字段,因此将其保留。我还使用了别名来进行查询(在我看来)更容易阅读。
第3个问题:
以及有多少保留在table_reservation.list_id上的table_reservation.list_id> 0
然后您可以在CASE
内使用条件聚合(SUM
表达式):
SELECT l.id,
l.quantity,
Reserved = SUM(r.quantity),
ReservedWithListOver0 = SUM(CASE WHEN r.list_id > 0 THEN r.[quantity] ELSE 0 END)
FROM table_location AS l
INNER JOIN table_things AS t
ON t.id = l.ID
LEFT JOIN table_reservation r
ON r.id = t.id
AND r.location = l.location
WHERE l.location = 100
GROUP BY l.id, l.quantity;
作为一些附注,除非您是出于正确的原因(因此根据执行查询的人查询不同的表),否则它是good idea to always use the schema prefix,即{{1}而不仅仅是dbo.table_reservation
。使用对象类型(即table_reservation
而不仅仅是dbo.table_things
)为对象名称添加前缀也相当陈旧。它有些受欢迎,但是this page给出了一个很好的例子,说明为什么它可能不是最好的主意。
答案 1 :(得分:0)
您可以使用如下查询:
SELECT tt.[id],
tl.[quantity],
tr.[total_quantity],
tr.[partial_quantity]
FROM table_location AS tl
INNER JOIN table_things AS tt ON tl.[id] = tt.[id]
LEFT JOIN (
SELECT id, location,
SUM(quantity) AS total_quantity,
SUM(CASE WHEN list_id > 0 THEN quantity ELSE 0 END) AS partial_quantity
FROM table_reservation
GROUP BY id, location
) AS tr ON tl.id = tr.id AND tl.location = tr.location
WHERE tl.location = 100
这里的诀窍是对表LEFT JOIN
的已聚合版本执行table_reservation
,以便每id, location
获得一行。派生表使用条件聚合来计算包含partial_quantity
的数量的字段list_id > 0
。
<强>输出:强>
id quantity total_quantity partial_quantity
-----------------------------------------------
1 10 3 2
2 1 1 0
答案 2 :(得分:0)
这是一个典型的情况,一个问题坐了几个小时无处可去,然后当你发布到stackoverflow时,你突然想出了答案。这是获取我想要的内容的查询:
SELECT table_things.[id],
table_location.[quantity],
SUM(table_reservation.[quantity],
(SELECT SUM(CASE WHEN table_reservation.list_id > 0 THEN ISNULL(table_reservation.[quantity], 0) ELSE 0 END)) AS test
FROM table_location
INNER JOIN table_things ON table_location.[id] = table_things.[id]
RIGHT OUTER JOIN table_reservation ON table_things.location = table_reservation.location AND table_things.[id] = table_reservation.[id]
WHERE table_location.location = 100
GROUP BY table_things.[id], table_location[quantity]
编辑:在阅读下面的GarethD回复后,我做了他建议的更改(对我的真实代码,而不是上面的查询),这使得(真实)查询更正。