简体   繁体   English

分组依据无法正常运行

[英]Group By not functioning as desired

Let's say I have three tables - Orders, OrderDetails, and ProductType - and the Orders table includes a column for Customer. 假设我有三个表-Orders,OrderDetails和ProductType-并且Orders表包括Customer列。 What I need to do is write a query that will show me a list of customers and how many orders each customer has placed, as well as displaying and grouping by another column, which is a boolean based on whether a particular type of product - say, telephones - is in the order. 我需要做的是编写一个查询,该查询将向我显示客户列表以及每个客户已下达多少订单,以及按另一列显示和分组,这是一个布尔值,取决于是否使用特定类型的产品-例如,电话-已在订购中。

For example, we might have: 例如,我们可能有:

Customer | 客户| NumOrders | NumOrders | IncludesPhone 包含电话
--------------------------------- ---------------------------------
Jameson | 詹姆森| 3 | 3 | Yes
Smith | 史密斯| 5 | 5 | Yes
Weber | 韦伯| 1 | 1 | Yes
Adams | 亚当斯| 2 | 2 | | | No 没有
Jameson | 詹姆森| 1 | 1 | No 没有
Smith | 史密斯| 7 | 7 | No 没有
Weber | 韦伯| 2 | 2 | No 没有

However, when I try to write the query for this, I'm getting multiple rows with the same values for Customer and IncludesPhone, each with a different value for NumOrders. 但是,当我尝试为此编写查询时,我得到多个行,它们的Customer和IncludesPhone值相同,每个行的NumOrders值都不同。 Why is this happening? 为什么会这样呢? My query is below: 我的查询如下:

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

Change the group by to 将群组更改为

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

This query should work 此查询应该工作

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

Since you're grouping on both Customer and Type , your query returns the count of orders per customer per type. 由于您同时在CustomerType上分组,因此查询将返回每种类型的每个客户的订单数。 If you only want one row per customer, you should only group by Customer , and then use something like this, to determine whether a given customer bought a phone: 如果只希望每个客户一行,则应仅按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

The inner sum basically counts the number of phones bought per customer. 内部总和基本上是计算每个客户购买的电话数量。 If this is more than 0, then the customer bought at least one phone and we return "Yes". 如果大于0,则客户购买了至少一部电话,我们返回“是”。

That's because you're grouping by Type column, so there could be duplicate rows. 那是因为您要按“ Type列进行分组,所以可能会有重复的行。 For example, for types 'Email' and 'Personal' column IncludesPhone will be 'No', but as you're grouping by Type there would be two records in the output. 例如,对于类型“电子邮件”和“个人”, IncludesPhone列将为“否”,但是当您按Type分组时,输出中将有两条记录。

To fix this, you can use same expression in the group by clause or use subquery or Common Table Expression : 要解决此问题,您可以在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

using same expression in the group by clause: 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

You could try this query: 您可以尝试以下查询:

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;

or this one: 或这一个:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM