【问题标题】:Trying to Find MAX value of a SUM query in SQL尝试在 SQL 中查找 SUM 查询的 MAX 值
【发布时间】:2018-07-27 19:28:25
【问题描述】:

我有 2 张桌子:

Product(ProductID, ProductName, ProductPrice, VendorID, CategoryID)

SoldVia(ProductID, TID, NoOfItems)

我需要显示销量最高的产品的产品 ID。我可以通过这个查询轻松得出按升序排序的列表:

SELECT distinct productid, sum(noofitems)
From soldvia
Group By productid
Order By sum(noofitems) DESC

问题是,我如何使用MAX 函数只显示列表的顶部值?我不能使用LIMITTOP 进行此分配,但是每当我使用MAX 时,我都会遇到各种聚合问题。

完成后,如何显示畅销产品的产品名称?

谢谢!

【问题讨论】:

  • SELECT DISTINCTGROUP BY 几乎没有必要。
  • 通过将您的查询变成带有别名的子查询,从而将其转换为派生表。然后从派生表中选择最大值。
  • @DanBracuk,你能告诉我这 2 个特定表的 SELECT 和 WHERE 是什么样的吗?

标签: sql join sum max teradata


【解决方案1】:

试试这个:

SELECT prd.ProductId
FROM Product prd
INNER JOIN SoldVia sld ON prd.ProductId = sld.ProductId
WHERE prd.NoOfItems = (SELECT MAX(NoOfItems) FROM SoldVia) -- Check for item that has max # items sold

这将返回聚合值最高的项目NoOfItems

更新

我不知道您在使用 Teradata。这让生活变得更轻松:)

SELECT ProductName
FROM Product prd
INNER JOIN (
  SELECT ProductId, SUM(NoOfItems) AS TotalItemsSold
  FROM SoldVia
  GROUP BY ProductId
  QUALIFY RANK() OVER(ORDER BY TotalItemsSold DESC) = 1 -- Only return ProductId(s) with largest TotalItemsSold value (includes ties)
) agg ON prd.ProductId = agg.ProductId -- Get aggregate # items sold (if any) 

只有在两个表中都有匹配的行时才会返回行。

【讨论】:

  • Teradata 返回 - [3809] 列“ProductId”不明确。
  • 糟糕...两个表都有该字段。只需限定参考 - 请参阅上面的更新。或者您可以将其替换为 ProductName,如果这是您想要的唯一字段。
  • 运行并得到 - [3810] 列/参数“DB_JUKIC_ZAGIMORE.prd.NoOfItems”不存在。我认为 Teradata 在识别别名时存在问题,但即使在我摆脱它们并将所有表名拼出之后,它仍然说数据库中不存在 WHERE 之后的“product.noofitems”
  • 对不起,我认为我原来的查询不正确。它只检查 MAX(NoOfItems) 值,而不是聚合。请参阅上面的更新查询。
【解决方案2】:

这有点简单,但我认为这仍然适合你

select productid, max(itemsum) 
from
(SELECT productid, sum(noofitems) as itemsum
FROM soldvia
group by productid)
; 

【讨论】:

  • 这可能适用于旧的 MySQL 版本,但不适用于其他 DBMS。
  • Teradata 吐出 [3707] 语法错误,应为名称或 Unicode 分隔标识符或 ')' 和 ';' 之间的 'UDFCALLNAME' 关键字。 ,但我认为在所有回复中,你可能是最接近真实答案的人(如果有的话)
  • 要摆脱语法错误,您必须将as agg添加到子选择中。但是你会得到3504 Selected non-aggregate values must be part of the associated group.。如果您添加分组,您最终只会进行两次聚合,而不会将结果限制在最大最大值。
  • @SQLdumbo:它没有关闭,因为它根本不起作用。
【解决方案3】:

基于@ravioli 的回答,没有子选择。

从逻辑上看,我更喜欢子选择(提前减少行数),但解释表明,子选择使用了多一步。我希望它对于更多的行会有所不同。

select
    S.ProductID
    , P.ProductName
    , sum(NoOfItems) as TotalItemsSold
from SoldVia as S
inner join Product as P
    on S.ProductID = P.ProductID
group by S.ProductID, P.ProductName
QUALIFY RANK() OVER(ORDER BY TotalItemsSold DESC) = 1 -- Only return ProductId(s) with largest TotalItemsSold
;

【讨论】:

  • 少一步并不意味着更有效率 :-) @ravioli 的答案将首先聚合和过滤,然后加入一个产品行(可能是几行),但是这将首先加入所有所有产品,然后聚合/过滤。有时优化器足够聪明,可以应用早期聚合,但在这种情况下可能不会。
  • @dnoeth 我完全同意。只是想添加它作为让优化器选择自己的方式而不是强迫他遵循我的想法的方式。至少值得一试,尤其是在数量众多且情况复杂的情况下。根据我的经验,他很聪明,只是有时我能打败他。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多