0

我有 2 张桌子。

表英雄 - 2 条记录

Name NVARCHAR(50)
PowerIds NVARCHAR(50) 

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

表权力 - 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

永远不要在一列中存储多个数据!

于 2013-07-26T16:31:58.320 回答
1

Try This:

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

Function:

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

Here you can find a SQL Fiddle example.

于 2013-07-26T16:56:44.903 回答