首页 > 解决方案 > 按另一列分组后在组中选择一列的值

问题描述

我将如何在以下查询中包含属于该特定类型的任何一本书的名称?

select distinct
(select sum(ob.Balance)),
ob.BookType
from orders.OrderBooks ob
group by ob.BookType

在其当前状态下,它会执行我需要的操作,并按BookType对书籍进行分组并汇总它们的余额,如下所示。

在此处输入图像描述

但是,我需要属于该BookType的任何书的名称作为结果的一部分。

如果我选择BookName列,然后按如下所示对其进行分组,则会产生更多唯一条目,并在一定程度上撤消原始分组。

select distinct
(select sum(ob.Balance)),
ob.BookType,
ob.BookName
from orders.OrderBooks ob
group by ob.BookType, ob.BookName

标签: sqlsql-servertsql

解决方案


;WITH x AS 
(
  SELECT 
    Balance = SUM(Balance) OVER (PARTITION BY BookType), 
    BookType,
    BookName,
    rn = ROW_NUMBER() OVER (PARTITION BY BookType ORDER BY BookName DESC)
  FROM orders.OrderBooks
)
SELECT Balance, BookType, BookName 
  FROM x 
  WHERE rn = 1;

db<>小提琴

ORDER BY BookName DESC是经销商的选择。如果您真的不在乎结果中显示的是哪个标题,您可以使用任何您喜欢的顺序。如果您希望结果每次都是随机的,您可以使用ORDER BY NEWID().

一般来说,我比TOP (1)子查询方法更喜欢这种灵活性,除了单次扫描而不是每行额外的表访问。但你也可以用不同的方式来做;也只取书名的最小/最大值:

SELECT Balance = SUM(Balance), 
       BookType,
       BookName = MIN(BookName) -- or MAX()
FROM dbo.OrderBooks
GROUP BY BookType;

你可以看到这些在这个 db<>fiddle 中给出了类似的结果。计划也更简单;最值得注意的是:没有线轴。但是,当您对该列使用聚合函数时,提供任意/随机结果变得更加困难,并且如果您打算添加从右行拉出的其他列,则需要返回 row_number 解决方案。


推荐阅读