获取最大值的SQL策略

时间:2016-11-14 23:29:06

标签: sql sql-server sql-server-2012

假设我有这三个表:

enter image description here

对于所有产品,我想得到的是product_id和最常见的客户(产品的最大客户)。

我解决了这个问题:

SELECT 
product_id AS product, 
(SELECT TOP 1 client_id FROM Bill_Item, Bill 
    WHERE Bill_Item.product_id = p.product_id
    and Bill_Item.bill_id = Bill.bill_id
GROUP BY
    client_id
ORDER BY
    COUNT(*) DESC
) AS client
FROM Product p

你知道更好的方法吗?

3 个答案:

答案 0 :(得分:2)

内部查询将为您提供排名。外部查询将为您提供最适合产品的客户

SELECT *
(
    SELECT i.product_id, b.client_id, 
           r = row_number() over (partition by i.product_id 
                                      order by count(*) desc)
    FROM   Bill b
           INNER JOIN Bill_Item i ON b.bill_id = i.bill_id
    GROUP BY i.product_id, b.client_id
) d
WHERE r = 1

答案 1 :(得分:1)

松鼠的答案不会归还从未销售过的产品。如果你想包含那些,那么你的方法是可以的,虽然我会把查询写成:

SELECT product_id as product, 
       (SELECT TOP 1 b.client_id
        FROM Bill_Item bi JOIN
             Bill b
             ON bi.bill_id = b.bill_id
        WHERE Bill_Item.product_id = p.product_id
        GROUP BY client_id
        ORDER BY COUNT(*) DESC
       ) as client
FROM Product p;

您也可以使用APPLY来表达这一点,但相关的子查询也可以。

请注意正确使用显式JOIN语法。

答案 2 :(得分:1)

我只使用Common Table Expression [CTE]而不是派生表提交与@Squirrell几乎相同的内容。所以我不会重复,但有一些关于您的查询的学习点。首先是IMPLICIT JOINS,例如FROM Bill_Item, Bill很容易产生意想不到的后果(很多问题之一:Queries that implicit SQL joins can't do?)接下来,对于计算列,您实际上可以在OUTER APPLY中执行此操作或CROSS APPLY这是一种非常有用的技术。

所以你可以按如下方式重写你的方法:

SELECT *
FROM
    Product p
    OUTER APPLY (SELECT TOP 1 b.client_id
             FROM
                Bill_Item bi
                INNER JOIN Bill b
                ON bi.bill_id = b.bill_id
             WHERE
                bi.product_id = p.product_id
             GROUP BY
                b.client_id
             ORDER BY
                COUNT(*) DESC) c

为了向您展示squirell的答案如何仍然包括从未销售过的产品,您只需将产品和LEFT JOIN加入其他表:

;WITH cte AS (
    SELECT
       p.product_id
       ,b.client_id
       ,ROW_NUMBER() OVER (PARTITION BY p.product_id ORDER BY COUNT(*) DESC) as RowNumber
    FROM
       Product p
       LEFT JOIN Bill_Item bi
       ON p.product_id = bi.product_id
       LEFT JOIN Bill b
       ON bi.bill_id = b.bill_id
    GROUP BY
       p.product_id
       ,b.client_id
)

SELECT *
FROM
    cte
WHERE
    RowNumber = 1

其中一些有用的技术。

  • CTE
  • 申请(外部和十字架)
  • 窗口功能