【问题标题】:Alternative SQL ANSI for TOP WITH TIESTOP WITH TIES 的替代 SQL ANSI
【发布时间】:2017-11-04 02:51:37
【问题描述】:

我有两张桌子:

产品

  • 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 更好吗?

【问题讨论】:

  • 你使用MAX(COUNT(*))的时候,有没有试过在HAVING使用?
  • 密集秩 ANSI SQL 标准的一部分,只有在您使用 MySQL 或少数其他数据库时才可用。依赖密集秩有什么问题?
  • 我尝试使用 SUBSELECT ON 必须获得最大值。但是我应该重复代码吗?
  • 哦,我不知道!我以为 DENSE_RANK 只是一个 SQL SERVER 函数。但是没有其他使用子查询的方法吗?我想比较一下性能。
  • dense_rank() 是要走的路。它不是特定于 SQL Server 的函数,例如在 SQL Server 知道它存在之前,Oracle 已经存在很长时间了

标签: sql sql-server subquery


【解决方案1】:

这是 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 标准的原因之一。

【讨论】:

  • 这也是一个很好的答案。但它不是 ANSI,对吧?我想知道一种仅使用子查询或另一种 ansi 方式的方法。谢谢
  • @OnScreen 让我删除 CTE。
  • 它真的很管用,我在想这样的事情。我认为这确实是仅使用子查询的最佳解决方案。我测试过,上面有领带,这个有相同的性能。 50%。谢谢,伙计!!!
  • @OnScreen: 第一个查询 ANSI SQL
猜你喜欢
  • 2012-03-26
  • 1970-01-01
  • 2014-04-05
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
相关资源
最近更新 更多