You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在SQL Server中如何对SELECT查询内相同值行分组?附现有查询语句

在SQL Server中对SELECT查询的行分组的方法

嘿,要在SQL Server的SELECT语句里对相同值的行分组,核心工具就是GROUP BY子句,另外如果不想合并行但需要分组统计的话,窗口函数OVER(PARTITION BY)也很实用。我结合你的查询语句来给你讲清楚:

一、基础分组:用GROUP BY合并相同值的行

GROUP BY的作用是把指定列值相同的行聚合为一组,通常需要配合聚合函数(比如SUM()COUNT()MAX()等)来计算每组的统计结果——毕竟分组后你总得对每组的数据做些汇总操作对吧?

结合你的查询语句调整示例

假设你想按Parcel(也就是pd.trackingno)分组,统计每个包裹的总发送数量、总金额,同时保留该包裹对应的订单、商品标识(这里假设同一包裹的订单/商品信息是一致的,或者你取每组的第一条),可以这样修改你的查询:

SELECT 
    pd.trackingno AS [Parcel],
    -- 取每组的第一个订单标识,组内值一致时用MAX()/MIN()都可以
    MAX(Trim(o.orderno) + '_' + CONVERT(NVARCHAR, pd.groupnum )) AS [Order],
    MAX(Isnull(vi.[gtin], '''')) AS [Item],
    MAX(Isnull(i.skuno, '')) AS [Article],
    MAX(Isnull(ix_clr.skuno, '')) AS [Color],
    MAX(Isnull(ix_sze.skuno, '')) AS [Size],
    MAX(Isnull(i.[description], '')) AS [Description],
    -- 聚合计算该包裹的总金额
    SUM(CONVERT(DECIMAL(8, 2), oi.unitprice * oi.quantity)) AS [TotalPrice],
    -- 聚合计算该包裹的总发送数量
    SUM(CONVERT(INT, oi.quantity)) AS [TotalSent]
FROM 
    (SELECT orderno, 'S' Type, groupnum FROM shipments WHERE shipbatch BETWEEN ...) pd
-- 保留你原查询里的表关联逻辑
JOIN orders o ON pd.orderno = o.orderno
JOIN orderitems oi ON o.orderno = oi.orderno
JOIN items i ON oi.itemid = i.itemid
LEFT JOIN variantinfo vi ON i.variantid = vi.variantid
LEFT JOIN itemxref ix_clr ON i.itemid = ix_clr.itemid AND ix_clr.xreftype = 'COLOR'
LEFT JOIN itemxref ix_sze ON i.itemid = ix_sze.itemid AND ix_sze.xreftype = 'SIZE'
-- 指定分组依据:按包裹号分组
GROUP BY pd.trackingno

注意:SQL Server有严格的语法要求——SELECT里的列要么是GROUP BY子句里的分组列,要么被聚合函数(比如MAX()SUM())包裹,否则会直接报错哦。

二、不合并行的分组统计:用窗口函数OVER(PARTITION BY)

如果你不想把相同值的行合并,只是想给每行标记分组信息(比如组内序号),或者计算组内的统计值(比如每个包裹的总金额,但保留每一行的商品明细),那用窗口函数会更合适:

比如给同一Parcel的行加上组内序号,同时计算该包裹的总发送数量:

SELECT 
    pd.trackingno AS [Parcel],
    Trim(o.orderno) + '_' + CONVERT(NVARCHAR, pd.groupnum ) AS [Order],
    Isnull(vi.[gtin], '''') AS [Item],
    Isnull(i.skuno, '') AS [Article],
    Isnull(ix_clr.skuno, '') AS [Color],
    Isnull(ix_sze.skuno, '') AS [Size],
    Isnull(i.[description], '') AS [Description],
    CONVERT(DECIMAL(8, 2), oi.unitprice * oi.quantity) AS [Price],
    CONVERT(INT, oi.quantity) AS [Sent],
    -- 组内序号:同一包裹里的行从1开始编号
    ROW_NUMBER() OVER(PARTITION BY pd.trackingno ORDER BY oi.quantity) AS [GroupRowNo],
    -- 组内总发送数量:同一包裹的所有Sent之和,每行都会显示这个汇总值
    SUM(CONVERT(INT, oi.quantity)) OVER(PARTITION BY pd.trackingno) AS [TotalGroupSent]
FROM 
    (SELECT orderno, 'S' Type, groupnum FROM shipments WHERE shipbatch BETWEEN ...) pd
-- 保留原查询的表关联逻辑
JOIN orders o ON pd.orderno = o.orderno
JOIN orderitems oi ON o.orderno = oi.orderno
JOIN items i ON oi.itemid = i.itemid
LEFT JOIN variantinfo vi ON i.variantid = vi.variantid
LEFT JOIN itemxref ix_clr ON i.itemid = ix_clr.itemid AND ix_clr.xreftype = 'COLOR'
LEFT JOIN itemxref ix_sze ON i.itemid = ix_sze.itemid AND ix_sze.xreftype = 'SIZE'

这种方式下,原来的每行数据都会保留,同时你能得到分组的统计信息,非常适合需要明细+分组汇总的场景。

内容的提问来源于stack exchange,提问作者Aswin Francis

火山引擎 最新活动