0

私は2つのテーブルを持っています。

テーブル ヒーローズ - 2 レコード

Name NVARCHAR(50)
PowerIds NVARCHAR(50) 

Name               PowerIds
'Hulk'             '1,3'
'Reed Richards'    '2'

Table Powers - 3 レコード

PowerId INT
PowerDescr NVARCHAR(50)

PowerId   PowerDescr
1         'Strength'
2         'Intelligence'
3         'Durability'

SELECT でこれを実現する最も賢い方法は次のとおりです。

Name               Powers
'Hulk'             'Strength, Durability'
'Reed Richards'    'Intelligence'

これはサードパーティ製品であるため、テーブル構造を変更することはできません。

4

2 に答える 2

4

最も賢い方法は、テーブルを正規化することです。Heroesテーブルを次のように変更します

Name               PowerId
'Hulk'             1
'Hulk'             3
'Reed Richards'    2

または、テーブルからパワーを削除しHeroesて、ヒーローへの参照とこのようなパワーのみを保持する別のテーブルを追加します

HeroID  PowerID
1       1
1       3
2       2

複数のデータを 1 つの列に格納しないでください。

于 2013-07-26T16:31:58.320 に答える
1

これを試して:

SELECT Name,
STUFF(
  (SELECT ',' + CAST(P.PowerDescr as VARCHAR(MAX))
  FROM fn_ParseCsvString(H1.PowerIds, ',') H2
  INNER JOIN Powers P ON P.PowerId = H2.ParsedString 
  FOR XML path('')),1,1,''
) AS Strength
FROM Heroes H1

関数:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[fn_ParseCsvString]
(   
    @csvString  VARCHAR(MAX),
    @delimiter  VARCHAR(MAX)
)
RETURNS @parsedStringTable TABLE (ParsedString VARCHAR(MAX))
AS
BEGIN
    DECLARE @startIndex INT, @targetedIndex INT
    SELECT
        @startIndex = 1
    WHILE @startIndex <= LEN(@CSVString)
    BEGIN
        SELECT  
            @targetedIndex = charindex(@Delimiter, @CSVString, @startIndex)
        IF @targetedIndex = 0
        BEGIN
            SELECT  
                @targetedIndex = len(@CSVString) + 1
        END
        INSERT  @parsedStringTable 
        SELECT 
            SUBSTRING(@CSVString, @startIndex, @targetedIndex - @startIndex)
        SELECT  @startIndex = @targetedIndex + LEN(@Delimiter)
    END
    RETURN
END


GO

ここでは、SQL Fiddle の例を見つけることができます。

于 2013-07-26T16:56:44.903 に答える