组不按预期运行

时间:2013-08-15 13:20:35

标签: sql sql-server-2008 group-by

假设我有三个表 - Orders,OrderDetails和ProductType - Orders表包含Customer列。我需要做的是编写一个查询,向我显示一个客户列表和每个客户放置了多少订单,以及显示和分组另一列,这是一个基于特定类型产品的布尔值 - 说,电话 - 在订单中。

例如,我们可能有:

Customer | NumOrders | IncludesPhone
---------------------------------
Jameson | 3 | Yes
Smith | 5 | Yes
Weber | 1 | Yes
Adams | 2 | | No
Jameson | 1 | No
Smith | 7 | No
Weber | 2 | No

但是,当我尝试为此编写查询时,我将获得具有相同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

5 个答案:

答案 0 :(得分:2)

将组更改为

GROUP BY    Customer, 
            CASE WHEN (ProductType.Type = 'Phone') THEN 'Yes' ELSE 'No' END

答案 1 :(得分:1)

此查询应该有效

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

答案 2 :(得分:0)

由于您要对CustomerType进行分组,因此您的查询会返回每个类型的每个客户的订单数。如果您只需要每个客户一行,则应该只按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,那么客户至少购买了一部手机,我们返回“是”。

答案 3 :(得分: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

答案 4 :(得分:0)

您可以尝试此查询:

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