0

Labs と LabUsers の 2 つのテーブルを含むデータベースがありLabUsersますLabs

具体的には、ラボのユーザー名を連結して黒丸 ( • is Alt+0149) で区切り、これらのユーザー名を左から右にアルファベット順に並べ替えたいと考えています。

ここに例があります。

テーブルは次のLabsようになります。

LabID  LabName     LabStudents
-----  ----------  -----------
1      North       NULL
2      North East  NULL
3      South West  NULL

LabUsers次のようになります。

LabUserID   LabUserName   LabID
---------   -----------   -----    
1           Diana         1
2           Paul          2
3           Paula         2
4           Romeo         1
5           Julia         1
6           Rose          2
7           Diana         2

Labsこの結果を表に表示したいと思います。

LabID  LabName     LabUsers
-----  ----------  ---------------------
1      North       Diana•Julia•Romeo
2      North East  Diana•Paul•Paula•Rose
3      South West  NULL

テーブルを作成するスクリプトは次のとおりです。

USE [tempdb];
GO
CREATE TABLE [dbo].[LabUsers]
(
    [LabUserID] [int] PRIMARY KEY CLUSTERED,
    [LabUserName] [nvarchar](50) NOT NULL,
    [LabID] [int] NOT NULL
);
GO
INSERT [dbo].[LabUsers] SELECT 1, N'Diana', 1;
INSERT [dbo].[LabUsers] SELECT 2, N'Paul',  2;
INSERT [dbo].[LabUsers] SELECT 3, N'Paula', 2;
INSERT [dbo].[LabUsers] SELECT 4, N'Romeo', 1;
INSERT [dbo].[LabUsers] SELECT 5, N'Julia', 1;
INSERT [dbo].[LabUsers] SELECT 6, N'Rose',  2;
INSERT [dbo].[LabUsers] SELECT 7, N'Diana', 2;

CREATE TABLE [dbo].[Labs]
(
    [LabID] [int] PRIMARY KEY CLUSTERED,
    [LabName] [nvarchar](50) NOT NULL,
    [LabUsers] [nvarchar](max) NULL
);
GO
INSERT [dbo].[Labs] SELECT 1, N'North',      NULL;
INSERT [dbo].[Labs] SELECT 2, N'North East', NULL;
INSERT [dbo].[Labs] SELECT 3, N'South West', NULL;
4

3 に答える 3

2

これを試してみてください

SELECT  LabName ,
        STUFF(( SELECT  ',' + LabUsers.LabUserName
                FROM    dbo.LabUsers
                WHERE   LabUsers.LabID = Labs.LabID
                ORDER BY LabName
              FOR
                XML PATH('')
              ), 1, 1, '') AS Labusers
FROM    dbo.Labs
ORDER BY LabName

FOR XML PATH('') は文字列を 1 つの XML 結果に連結し、STUFF は最初の文字に「何もない」文字を置きます。たとえば、不要な最初のカンマを消去します。

于 2012-05-21T23:43:49.313 に答える
2
SELECT l.LabID, l.LabName, LabUsers = STUFF((SELECT N'•' + lu.LabUserName
  FROM dbo.LabUsers AS lu 
  WHERE lu.LabID = l.LabID
  ORDER BY lu.LabUserName
  FOR XML PATH(''), 
  TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
FROM dbo.Labs AS l;

クエリを実行すると、実行時にコードをいつでも生成できるため、これをテーブルに格納する理由はまったくありません。テーブルに保存すると、テーブル内の行を変更するたびに更新する必要があります。

ただし、これを行わないように説得できない場合 (このように冗長なデータを保存するのは本当に悪いことです)、次の方法を試すことができます。

;WITH x AS
(
    SELECT l.LabID, l.LabName, x = STUFF((SELECT N'•' + lu.LabUserName
      FROM dbo.LabUsers AS lu 
      WHERE lu.LabID = l.LabID
      ORDER BY lu.LabUserName
      FOR XML PATH(''), 
      TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
    FROM dbo.Labs AS l
)
UPDATE l
SET LabUsers = x.x
FROM dbo.Labs AS l
INNER JOIN x ON l.LabID = x.LabID;

パフォーマンス テストに関しては、上記のバージョンとこのバリエーションを比較します。

SELECT l.LabID, l.LabName, LabUsers = STUFF((SELECT N'•' + lu.LabUserName
  FROM dbo.LabUsers AS lu 
  WHERE lu.LabID = l.LabID
  ORDER BY lu.LabUserName
  FOR XML PATH('')), 1, 1, '')
FROM dbo.Labs AS l;

私のシステムでは、この回答の上部にある初期バージョンがはるかに高価であることがわかります。また、これらのアプローチをユーザー定義関数に詰め込む (しゃれた意図はありません) と、@RThomas が提案する連結方法に近づけることにも注意してください。

于 2012-05-21T23:40:03.677 に答える
0

これを行う別の方法は、次のように、すべてのラボ ユーザーを単一の文字列として返す UDF を設定することです。

CREATE FUNCTION LabUserString
(
@pLabId Int
)
RETURNS NVarChar(Max)
AS
BEGIN

  Declare @pResult NVarChar(Max)

  SELECT @pResult = COALESCE(@pResult + N'•', '') + [LabUserName] 
  FROM LabUsers WHERE LabId = @pLabId

  Return @pResult

END

そして、次のようなクエリ:

Select LabID, LabName, dbo.LabUserString(LabID) AS LabUsers FROM Labs
于 2012-05-21T23:45:41.043 に答える