【问题标题】:Sql concatenate of row data into columnSql将行数据连接到列中
【发布时间】:2015-12-29 06:29:54
【问题描述】:

数据集:

+-----------------+--------+---------+
|     TransNo     | Serial | Project |
+-----------------+--------+---------+
| A00000000000001 |      1 |     100 |
| A00000000000001 |      2 |     200 |
| A00000000000001 |      3 |     201 |
| A00000000000001 |      4 |     101 |
| A00000000000002 |      1 |     100 |
| A00000000000002 |      2 |     101 |
| A00000000000003 |      1 |     100 |
| A00000000000003 |      2 |     200 |
| A00000000000004 |      1 |     200 |
| A00000000000004 |      2 |     100 |
| A00000000000005 |      1 |     101 |
| A00000000000005 |      2 |     100 |
+-----------------+--------+---------+

我想按项目和按事务分区以新列顺序合并项目,如下所示。 [项目将按 ASC 顺序合并]

输出:

    +-----------------+--------+---------+------------------+
    |     TransNo     | Serial | Project | CProject         |
    +-----------------+--------+---------+------------------+
    | A00000000000001 |      1 |     100 |     100101200201 |
    | A00000000000001 |      2 |     200 |     100101200201 |
    | A00000000000001 |      3 |     201 |     100101200201 |
    | A00000000000001 |      4 |     101 |     100101200201 |
    | A00000000000002 |      1 |     100 |     100101       |
    | A00000000000002 |      2 |     101 |     100101       |
    | A00000000000005 |      1 |     101 |     100101       |
    | A00000000000005 |      2 |     100 |     100101       |
    | A00000000000003 |      1 |     100 |     100200       |
    | A00000000000003 |      2 |     200 |     100200       |
    | A00000000000004 |      1 |     200 |     100200       |
    | A00000000000004 |      2 |     100 |     100200       |
    +-----------------+--------+---------+------------------+

更新 1:

如果我希望我的输出顺序是串行而不是项目,该怎么办。

    +-----------------+--------+---------+------------------+
    |     TransNo     | Serial | Project | CProject         |
    +-----------------+--------+---------+------------------+
    | A00000000000001 |      1 |     100 |     100200201101|
    | A00000000000001 |      2 |     200 |     100200201101|
    | A00000000000001 |      3 |     201 |     100200201101|
    | A00000000000001 |      4 |     101 |     100200201101|
    | A00000000000002 |      1 |     100 |     100101       |
    | A00000000000002 |      2 |     101 |     100101       |
    | A00000000000005 |      1 |     101 |     101100       |
    | A00000000000005 |      2 |     100 |     101100       |
    | A00000000000003 |      1 |     100 |     100200       |
    | A00000000000003 |      2 |     200 |     100200       |
    | A00000000000004 |      1 |     200 |     200100       |
    | A00000000000004 |      2 |     100 |     200100       |
    +-----------------+--------+---------+------------------+

【问题讨论】:

  • “CProject”下的数字有什么意义?我没有看到明显的模式。
  • For transNo 'A00000000000001 ' CProject 是其所有项目的升序合并。请参阅此交易存在 4 个项目 100、200、201、101,通过按 ASC 顺序合并它们,它将是 100101200201

标签: sql sql-server sql-server-2012


【解决方案1】:
DECLARE @t TABLE (
    TransNo VARCHAR(20),
    Serial INT,
    Project INT
)

INSERT INTO @t (TransNo, Serial, Project)
VALUES
    ('A00000000000001', 1, 100),
    ('A00000000000001', 2, 200),
    ('A00000000000001', 3, 201),
    ('A00000000000001', 4, 101),
    ('A00000000000002', 1, 100),
    ('A00000000000002', 2, 101),
    ('A00000000000003', 1, 100),
    ('A00000000000003', 2, 200),
    ('A00000000000004', 1, 200),
    ('A00000000000004', 2, 100),
    ('A00000000000005', 1, 101),
    ('A00000000000005', 2, 100)

SELECT *, CProject = (
    SELECT DISTINCT [text()] = t2.Project
    FROM @t t2
    WHERE t2.TransNo = t1.TransNo
    ORDER BY t2.Project
    FOR XML PATH('')
)
FROM @t t1

输出 -

TransNo              Serial      Project     CProject
-------------------- ----------- ----------- --------------
A00000000000001      1           100         100101200201
A00000000000001      2           200         100101200201
A00000000000001      3           201         100101200201
A00000000000001      4           101         100101200201
A00000000000002      1           100         100101
A00000000000002      2           101         100101
A00000000000003      1           100         100200
A00000000000003      2           200         100200
A00000000000004      1           200         100200
A00000000000004      2           100         100200
A00000000000005      1           101         100101
A00000000000005      2           100         100101

[text()] -

100101200201

没有[text()] -

<Project>100</Project><Project>101</Project><Project>200</Project><Project>201</Project>

更多详情 - http://www.codeproject.com/Articles/691102/String-Aggregation-in-the-World-of-SQL-Server

更新 -

SELECT *, CProject = (
    SELECT [text()] = t2.Project
    FROM (
        SELECT t2.Project, Serial = MIN(t2.Serial)
        FROM @t t2
        WHERE t2.TransNo = t1.TransNo
        GROUP BY t2.Project
    ) t2
    ORDER BY t2.Serial
    FOR XML PATH('')
)
FROM @t t1

【讨论】:

  • 非常优雅的解决方案!
  • 好极了!!!但是一个小问题。假设项目 100、200、200、101 是否有可能返回 100101200 ??
  • 嗨 Devart,[text()] 是什么,它是来自 xpath 的函数吗?
  • @Ogrish Man, text() 函数只检索没有节点的元素值
  • @Smart003 不客气 ;) 也可以查看这篇文章 - blog.devart.com/xml-xquery-perfomance-issues.html 愿原力与你同在 :))
【解决方案2】:

试试这个方法

SELECT t1.*,t2.CProject
FROM t AS t1
JOIN (
    SELECT SS.TransNo, (
            SELECT ' ' + US.Project     
            FROM t US
            WHERE US.TransNo = SS.TransNo
            FOR XML PATH('')
        ) CProject
    FROM t SS
    GROUP BY SS.TransNo
    ORDER BY SS.Serial
) t2 ON t1.TransNo = t2.TransNo

【讨论】:

  • GROUP_CONCAT 不存在于SQL Server
  • 错误:ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效,除非还指定了 TOP、OFFSET 或 FOR XML。
  • 子查询中的排序可能会导致意想不到的结果
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
相关资源
最近更新 更多