SQL 查询连接多个记录中的值

发布于 2024-09-13 08:27:07 字数 596 浏览 6 评论 0原文

我有一个包含雇员的表Employees(假设重要字段是ID int、Name varchar(50))和一个包含销售区域的表Areas(ID int、EmployeeID int、USState char(2))。

示例值是:

Employees
ID     Name
1      Shoeman
2      Smith
3      Johnson

Areas
ID     EmployeeID     USState
1      1              NY
2      1              FL
3      1              AR
4      2              DC
5      2              AR
6      3              TX

任何人都可以给我一个有关通过以下方式进行 SQL 查询来获取输出记录集的提示:

EmployeeID     USState
1              NY FL AR
2              DC AR
3              TX

目标平台:SQL Server 2005。

I've got a table Employees with employees (say the important fields are ID int, Name varchar(50)) and a table Areas with sales areas (ID int, EmployeeID int, USState char(2)).

The sample values are:

Employees
ID     Name
1      Shoeman
2      Smith
3      Johnson

Areas
ID     EmployeeID     USState
1      1              NY
2      1              FL
3      1              AR
4      2              DC
5      2              AR
6      3              TX

Can anyone give me a hint on making a SQL query to get the output recordset in the following way:

EmployeeID     USState
1              NY FL AR
2              DC AR
3              TX

Target platform: SQL Server 2005.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伴梦长久 2024-09-20 08:27:07

此操作称为 GROUP_CONCAT 在 MySQL 中,但 SQL Server 不支持它。

在 SQL Server 中,您可以使用 FOR XML PATH 来模拟相同的功能 黑客。

SELECT extern.EmployeeID, states AS USState
FROM Areas AS extern
CROSS APPLY (
    SELECT USState + ' '
    FROM Areas AS intern
    WHERE extern.EmployeeID = intern.EmployeeID
    FOR XML PATH('')
) T1 (states)
GROUP BY extern.EmployeeID, states
ORDER BY extern.EmployeeID

另一种方法是使用递归 CTE。这是一个不那么棘手的解决方案,但也更复杂:

WITH qs(EmployeeID, USState, rn, cnt) AS
(
    SELECT
        EmployeeID,
        USState,
        ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY USState),
        COUNT(*) OVER (PARTITION BY EmployeeID)
    FROM    Areas
),
t (EmployeeID, prodname, gc, rn, cnt) AS
(
    SELECT EmployeeID, USState, CAST(USState AS NVARCHAR(MAX)), rn, cnt
    FROM qs
    WHERE rn = 1
    UNION ALL
    SELECT
        qs.EmployeeID, qs.USState,
        CAST(t.gc + ' ' + qs.USState AS NVARCHAR(MAX)),
        qs.rn, qs.cnt
    FROM t
    JOIN qs ON qs.EmployeeID = t.EmployeeID
           AND qs.rn = t.rn + 1
)
SELECT EmployeeID, gc AS USState
FROM   t
WHERE  rn = cnt
ORDER BY EmployeeID
OPTION (MAXRECURSION 0)

两种方法都会给出您想要的结果:

EmployeeID     USState
1              NY FL AR 
2              DC AR 
3              TX 

This operation is called GROUP_CONCAT in MySQL but SQL Server doesn't support it.

In SQL Server you can simulate the same functionality using the FOR XML PATH hack.

SELECT extern.EmployeeID, states AS USState
FROM Areas AS extern
CROSS APPLY (
    SELECT USState + ' '
    FROM Areas AS intern
    WHERE extern.EmployeeID = intern.EmployeeID
    FOR XML PATH('')
) T1 (states)
GROUP BY extern.EmployeeID, states
ORDER BY extern.EmployeeID

An alternative is to use a recursive CTE. This is a less hacky solution but it is also more complicated:

WITH qs(EmployeeID, USState, rn, cnt) AS
(
    SELECT
        EmployeeID,
        USState,
        ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY USState),
        COUNT(*) OVER (PARTITION BY EmployeeID)
    FROM    Areas
),
t (EmployeeID, prodname, gc, rn, cnt) AS
(
    SELECT EmployeeID, USState, CAST(USState AS NVARCHAR(MAX)), rn, cnt
    FROM qs
    WHERE rn = 1
    UNION ALL
    SELECT
        qs.EmployeeID, qs.USState,
        CAST(t.gc + ' ' + qs.USState AS NVARCHAR(MAX)),
        qs.rn, qs.cnt
    FROM t
    JOIN qs ON qs.EmployeeID = t.EmployeeID
           AND qs.rn = t.rn + 1
)
SELECT EmployeeID, gc AS USState
FROM   t
WHERE  rn = cnt
ORDER BY EmployeeID
OPTION (MAXRECURSION 0)

Both methods give the result you want:

EmployeeID     USState
1              NY FL AR 
2              DC AR 
3              TX 
深海不蓝 2024-09-20 08:27:07

这是我首选的使用 UDF 的格式(在大型数据库上似乎也更快)

CREATEFUNCTION dbo.StateList(@ID int) RETURNS varchar(max)

AS

DECLARE @out varchar(max);

SET @out=''; -- comment this out to reutrn NULL if nothing found

SELECT @out=@out+USState+' ' -- operates like a loop assigning the values in sequence to the out variable.

FROM AREAS
WHERE EmployeeID=@ID
ORDER BY USState

RETURN @out

查询示例...

SELECT Name, dbo.StateList(EmployeeID)
FROM Employees
Order BY Name

通过这种方式,您可以为希望以这种方式分解的每个列表创建一个 UDF。

This is my perfered format to use a UDF (appears to be much faster as well on a large DB)

CREATEFUNCTION dbo.StateList(@ID int) RETURNS varchar(max)

AS

DECLARE @out varchar(max);

SET @out=''; -- comment this out to reutrn NULL if nothing found

SELECT @out=@out+USState+' ' -- operates like a loop assigning the values in sequence to the out variable.

FROM AREAS
WHERE EmployeeID=@ID
ORDER BY USState

RETURN @out

Query example ...

SELECT Name, dbo.StateList(EmployeeID)
FROM Employees
Order BY Name

In this manner you create one UDF for each list you wish to explode in this way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文