替代SQL ANSI for TOP WITH TIES

时间:2017-11-04 02:51:37

标签: sql sql-server subquery

我有两张桌子:

产品

  • id_product
  • 描述
  • id_category

类别

  • id_category
  • 描述

我想知道有更多产品的类别。例如,类别食品有10种产品和电子产品。他们是一样的。

现在我正在使用SQL Server,而我正在使用TOP WITH TIES。

SELECT TOP 1 WITH TIES p.id_category, COUNT(*) as amount FROM product p 
JOIN category c ON p.id_category = c.id_category
GROUP BY p.id_category
ORDER BY amount 

还有另一种解决方法,性能良好吗? 我也尝试使用DENSE_RANK,其中位置= 1。 它也有效。

SELECT * FROM (
SELECT p.id_category, COUNT(*) as amount, DENSE_RANK() OVER (ORDER BY COUNT(*) DESC)  position FROM product p 
JOIN category c ON p.id_category = c.id_category
GROUP BY p.id_category
) rnk
WHERE rnk.position = 1

但我想在SQL ANSI中使用此解决方案。

我尝试使用MAX(COUNT(*)),但它不起作用。

有一般解决方案吗?这种解决方案比使用TOP WITH TIES更好吗?

1 个答案:

答案 0 :(得分:2)

以下是SQL Server的第三个选项:

WITH cte AS (
    SELECT p.id_category, COUNT(*) AS cnt
    FROM product p 
    INNER JOIN category c
        ON p.id_category = c.id_category
    GROUP BY p.id_category
)

SELECT *
FROM cte
WHERE cnt = (SELECT MAX(cnt) FROM cte);

如果您也不能依赖CTE,您可以轻松地将CTE内联到查询中。从性能的角度来看,DENSE_RANK可能会胜过我的回答。

删除CTE后,这将成为:

SELECT *
FROM
(
    SELECT p.id_category, COUNT(*) AS cnt
    FROM product p 
    INNER JOIN category c
        ON p.id_category = c.id_category
    GROUP BY p.id_category
)
WHERE cnt = (SELECT MAX(cnt) FROM (
                 SELECT p.id_category, COUNT(*) AS cnt
                 FROM product p 
                 INNER JOIN category c
                     ON p.id_category = c.id_category
                 GROUP BY p.id_category
            ));

此查询甚至可以在MySQL上运行。正如您所看到的,查询很难看,这就是将CTE和分析函数之类的东西引入ANSI标准的原因之一。