在 Microsoft SQL Server 2005 中模拟 group_concat MySQL 函数?

我正在尝试将基于 MySQL 的应用程序迁移到 Microsoft SQL Server 2005(不是出于选择,但就是这样).

I'm trying to migrate a MySQL-based app over to Microsoft SQL Server 2005 (not by choice, but that's life).

在最初的应用程序中,我们几乎使用了完全符合 ANSI-SQL 的语句,但有一个重要的例外——我们相当频繁地使用 MySQL 的 group_concat 函数.

In the original app, we used almost entirely ANSI-SQL compliant statements, with one significant exception -- we used MySQL's group_concat function fairly frequently.

group_concat 是这样做的:给定一个表,比如员工姓名和项目......

group_concat, by the way, does this: given a table of, say, employee names and projects...

SELECT empName, projID FROM project_members;

返回:

ANDY   |  A100
ANDY   |  B391
ANDY   |  X010
TOM    |  A100
TOM    |  A510

...这是您使用 group_concat 获得的结果:

... and here's what you get with group_concat:

SELECT 
    empName, group_concat(projID SEPARATOR ' / ') 
FROM 
    project_members 
GROUP BY 
    empName;

返回:

ANDY   |  A100 / B391 / X010
TOM    |  A100 / A510

所以我想知道的是:是否可以在 SQL Server 中编写一个用户定义的函数来模拟 group_concat 的功能?

So what I'd like to know is: Is it possible to write, say, a user-defined function in SQL Server which emulates the functionality of group_concat?

我几乎没有使用 UDF、存储过程或类似的东西的经验,只是直接的 SQL,所以请不要过多解释:)

I have almost no experience using UDFs, stored procedures, or anything like that, just straight-up SQL, so please err on the side of too much explanation :)

推荐答案

没有真正简单的方法可以做到这一点.不过,这里有很多想法.

No REAL easy way to do this. Lots of ideas out there, though.

我找到的最好的一个:

SELECT table_name, LEFT(column_names , LEN(column_names )-1) AS column_names
FROM information_schema.columns AS extern
CROSS APPLY
(
    SELECT column_name + ','
    FROM information_schema.columns AS intern
    WHERE extern.table_name = intern.table_name
    FOR XML PATH('')
) pre_trimmed (column_names)
GROUP BY table_name, column_names;

或者如果数据可能包含诸如 <

Or a version that works correctly if the data might contain characters such as <

WITH extern
     AS (SELECT DISTINCT table_name
         FROM   INFORMATION_SCHEMA.COLUMNS)
SELECT table_name,
       LEFT(y.column_names, LEN(y.column_names) - 1) AS column_names
FROM   extern
       CROSS APPLY (SELECT column_name + ','
                    FROM   INFORMATION_SCHEMA.COLUMNS AS intern
                    WHERE  extern.table_name = intern.table_name
                    FOR XML PATH(''), TYPE) x (column_names)
       CROSS APPLY (SELECT x.column_names.value('.', 'NVARCHAR(MAX)')) y(column_names) 

相关文章