SQL Server SQL行汇总和连接字符串

bxpogfeg  于 2022-11-21  发布在  其他
关注(0)|答案(2)|浏览(235)

我 在 SQL Server 中 有 这样 一 个 表 :
| 识别 码|等级|标签|名称 名称 名称|尺寸 大小|序号|
| - -| - -| - -| - -| - -| - -|
| 一 个|一 个||一 个|十四|七 个|
| 2 个|2 个|A 级|两 个|十二|四 个|
| 三 个|2 个|乙|三 个|第 0 页|五 个|
| 四 个|2 个|C 语言|四 个|第 0 页|六 个|
| 五 个|三 个||五 个|八 个|一 个|
| 六 个|四 个|A 级|六 个|十八|2 个|
| 七 个|四 个|乙|第 七 章|第 0 页|三 个|

  • " ID " 是 标识 字段 。
  • Rank 是 一 个 始终 递增 的 整数 , 其 作用 与 " Tag " 相同
  • " 标记 " 将 行 组合 到 " 单一 " 或 " 多 个 " 类型 行 中 :如果 " 标签 " 为 空白 或 空 值 , 则 单独 选择 该行 ( 单个 ) 。 如果 为 " A " 、 " B " 、 " C " 或 " D " , 则 必须 通过 连接 以 逗号 分隔 的 " 名称 " 字段 , 将 它们 全部 汇总 为 一 个 " A " ( 多 个 ) 行 。
  • 汇总 行 的 " 大小 " 值 是 ' A ' 行 的 值 。 对于 具有 ' B'、 ' C ' 或 ' D ' 的 所有 行 , 大小 为 零 , 汇总 时 将 采用 前 一 个 ' A ' 值 。
  • 最 后 , Seq 字段 是 用户 指定 的 排序 顺序 值 , 即 最终 的 ORDER BY 字段 。

因此 , 我 需要 以下 输出 :
| 标签|名称 名称 名称|尺寸 大小|
| - -| - -| - -|
| | 五 个|八 个|
| A 级|六 、 七|十八|
| A 级|二 、 三 、 四|十二|
| | 一 个|十四|
我 知道 我 需要 子 查询 和 一些 GROUP BY 和/或 PARTITION BY 的 组合 , 再 加上 ROW _ OVER 来 汇总 行 。 我 已经 尝试 了 我 能 想到 的 所有 组合 , 但 都 没有 成功 。 必须 有 TSQL 查询 来 完成 这项 工作 , 而 不 需要 求助 于 游标 。 有人 能 帮忙 吗 ? 提前 感谢 。

ktca8awb

ktca8awb1#

select   min(tag)               as tag
        ,string_agg(name, ', ') as name
        ,sum(size)              as size
from     t
group by rank

| 标签|姓名|大小|
| - -|- -|- -|
| 零值|一个|十四|
| A级|二、三、四|十二|
| 零值|五个|八个|
| A级|六、七|十八|
Fiddle

c9qzyr3d

c9qzyr3d2#

通过 查看 需求 , 我 发现 我们 是 按 rank 列 分组 的 。 此外 , 一些 字段 是 按 行 确定 的 , 其中 tag 值 为 A , 但 并 不 总是 存在 。
考虑 到 这 一 点 , 我们 需要 为 每个 rank 选择 一 个 " 种子 " 行 , 最 简单 的 方法 是 使用 row_number() 函数 在 每个 秩 内 排序 , 然后 选择 第 一 行 :

SELECT *
FROM (
    SELECT *, row_number() over (partition by rank order by case when tag = 'A' then 0 when coalesce(tag,'') = '' then 1 else 2 end, tag) as rn
    FROM [table]
) t
WHERE rn = 1

中 的 每 一 个
现在 我们 知道 了 哪 一 行 作为 每个 排名 的 基础 , 但 这 还 不够 。 我们 还 需要 知道 相同 排名 的 其他 名称 值 。 如果 我们 将 第 一 个 查询 和 JOIN 返回 到 基于 rank 的 同一 个 表 , 然后 使用 GROUP BY + STRING_AGG() 来 获得 最终 字段 , 我们 就 可以 找到 这 一 点 。 为了 方便 起见 ,我 将 使用 第 一 个 查询 作为 CTE :

WITH base_rows AS (
    SELECT rank, size, tag, seq, rn
    FROM (
        SELECT *, row_number() over (partition by rank order by case when tag = 'A' then 0 when coalesce(tag,'') = '' then 1 else 2 end, tag) as rn
        FROM [table]
    ) t
    WHERE rn = 1
)
SELECT b.tag, string_agg(t.name,',') names, b.size
FROM base_rows b
INNER JOIN [table] t ON t.rank = b.rank
GROUP BY b.rank, b.tag, b.size, b.seq
ORDER BY b.Seq

格式
在 此 查看 其 工作 原理 :
https://dbfiddle.uk/jt7m_EpK 的 最 大 值

相关问题