[英]Group By not functioning as desired
假设我有三个表-Orders,OrderDetails和ProductType-并且Orders表包括Customer列。 我需要做的是编写一个查询,该查询将向我显示客户列表以及每个客户已下达多少订单,以及按另一列显示和分组,这是一个布尔值,取决于是否使用特定类型的产品-例如,电话-已在订购中。
例如,我们可能有:
客户| NumOrders | 包含电话
---------------------------------
詹姆森| 3 | 是
史密斯| 5 | 是
韦伯| 1 | 是
亚当斯| 2 | | 没有
詹姆森| 1 | 没有
史密斯| 7 | 没有
韦伯| 2 | 没有
但是,当我尝试为此编写查询时,我得到多个行,它们的Customer和IncludesPhone值相同,每个行的NumOrders值都不同。 为什么会这样呢? 我的查询如下:
SELECT Customer, COUNT(Customer) AS NumOrders, CASE WHEN (ProductType.Type = 'Phone') THEN 'Yes' ELSE 'No' END AS IncludesPhone
FROM Orders INNER JOIN OrderDetails INNER JOIN ProductType
GROUP BY Customer, Type
Order By IncludesPhone, Customer
将群组更改为
GROUP BY Customer,
CASE WHEN (ProductType.Type = 'Phone') THEN 'Yes' ELSE 'No' END
此查询应该工作
SELECT Customer, COUNT(Customer) AS NumOrders,
CASE WHEN (ProductType.Type = 'Phone') THEN 'Yes' ELSE 'No' END AS IncludesPhone
FROM Orders INNER JOIN OrderDetails INNER JOIN ProductType
GROUP BY Customer,
CASE WHEN (ProductType.Type = 'Phone') THEN 'Yes' ELSE 'No' END
Order By IncludesPhone, Customer
由于您同时在Customer
和Type
上分组,因此查询将返回每种类型的每个客户的订单数。 如果只希望每个客户一行,则应仅按Customer
分组,然后使用类似的方法来确定给定的客户是否购买了电话:
SELECT Customer, COUNT(Customer) AS NumOrders,
CASE
WHEN SUM(CASE WHEN (ProductType.Type = 'Phone') THEN 1 ELSE 0 END) > 0
THEN 'Yes'
ELSE 'No' END AS IncludesPhone
FROM Orders INNER JOIN OrderDetails INNER JOIN ProductType
GROUP BY Customer
Order By IncludesPhone, Customer
内部总和基本上是计算每个客户购买的电话数量。 如果大于0,则客户购买了至少一部电话,我们返回“是”。
那是因为您要按“ Type
列进行分组,所以可能会有重复的行。 例如,对于类型“电子邮件”和“个人”, IncludesPhone
列将为“否”,但是当您按Type
分组时,输出中将有两条记录。
要解决此问题,您可以在group by
子句中使用相同的表达式,或者使用子查询或Common Table Expression :
with cte as (
select
Customer,
case when pt.Type = 'Phone' then 'Yes' else 'No' end as IncludesPhone
from Orders as o
inner join OrderDetails as od -- ???
inner join ProductType as pt -- ???
)
select Customer, IncludesPhone, count(*) as NumOrders
from cte
group by Customer, IncludesPhone
order by IncludesPhone, Customer
在group by
子句中使用相同的表达式:
select
Customer,
case when pt.Type = 'Phone' then 'Yes' else 'No' end as IncludesPhone,
count(*) as NumOrders
from Orders as o
inner join OrderDetails as od -- ???
inner join ProductType as pt -- ???
group by Customer, case when pt.Type = 'Phone' then 'Yes' else 'No' end
您可以尝试以下查询:
SELECT x.Customer,x.NumOrders,
CASE WHEN x.NumOrders>0 AND EXISTS(
SELECT *
FROM Orders o
INNER JOIN OrderDetails od ON ...
INNER JOIN ProductType pt ON ...
WHERE o.Customer=x.Customer
AND pt.Type = 'Phone'
) THEN 1 ELSE 0 END IncludesPhone
FROM
(
SELECT Customer,COUNT(Customer) AS NumOrders
FROM Orders
GROUP BY Customer
) x
Order By IncludesPhone, x.Customer;
或这一个:
SELECT o.Customer,
COUNT(o.Customer) AS NumOrders,
MAX(CASE WHEN EXISTS
(
SELECT *
FROM OrderDetails od
JOIN ProductType pt ON ...
WHERE o.OrderID=od.OrderID -- Join predicated between Orders and OrderDetails table
AND ProductType.Type = 'Phone'
) THEN 1 ELSE 0 END) AS IncludesPhone
FROM Orders o
GROUP BY Customer
ORDER BY IncludesPhone, o.Customer
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.