Sql-Server-2008

SQL Server 2008 - 使用其他表中的數據替換視圖行中的 csv 子字元串

  • July 9, 2020

使用 SQL Server 2008,有沒有辦法在視圖中執行 SELECT 查詢,將包含逗號分隔值的行替換為來自另一個表的相應文本值?STRING_SPLIT 和 STRING_AGG 在 2008 版本中不可用。

編輯: 添加了創建和插入腳本

CREATE TABLE Data(
Id int,
Value1 varchar(50) NULL,
Value2 int NULL,
Value3 datetime
)
GO

CREATE TABLE CodeValue(
   Id int,
   Code varchar(50) NULL
)
GO

INSERT [dbo].[Data] ([Id], [Value1], [Value2], [Value3]) VALUES (1, N'0;1;2', 43, CAST(N'2020-07-09T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Data] ([Id], [Value1], [Value2], [Value3]) VALUES (2, N'0;2;3', 652, CAST(N'2020-07-03T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Data] ([Id], [Value1], [Value2], [Value3]) VALUES (3, N'2', 1234, CAST(N'2020-07-02T00:00:00.000' AS DateTime))
GO

INSERT [dbo].[CodeValue] ([Id], [Code]) VALUES (0, N'Apple')
GO
INSERT [dbo].[CodeValue] ([Id], [Code]) VALUES (1, N'Orange')
GO
INSERT [dbo].[CodeValue] ([Id], [Code]) VALUES (2, N'Banana')
GO
INSERT [dbo].[CodeValue] ([Id], [Code]) VALUES (3, N'Dogmeat')
GO

考慮我的視圖包含來自兩個表的數據;Data 和 CodeValue,看起來像這樣:

Data
Id | Value | Value2 | Value 3
==============================
 1| 0;1;2| some other data
 2| 0;2;3|
 3| 2    |

CodeValue
Id | Code
=============
 0| Apple
 1| Orange
 2| Banana
 3| Dogmeat

因此,在我看來,SELECT 查詢的實際輸出將是:

View
Id | Value 
============
 1| Apple, Orange, Banana
 2| Apple, Banana, Dogmeat
 3| Banana

我已經搞砸了儲存過程和函式,但無法理解這些以及如何實際實現它。

編輯 2: 使用以下模板嘗試使用 STUFF():

WITH CTE_TableName AS (
      SELECT FieldA, FieldB
        FROM TableName)
SELECT t0.FieldA
    , STUFF((
      SELECT ',' + t1.FieldB
        FROM CTE_TableName t1
       WHERE t1.FieldA = t0.FieldA
       ORDER BY t1.FieldB
         FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
 FROM CTE_TableName t0
GROUP BY t0.FieldA
ORDER BY FieldA;

但是,我似乎無法使用自製的 split_string 函式在拆分值上加入 codeValues:

CREATE FUNCTION dbo.tvf_SplitString (@stringToSplit VARCHAR(100))
RETURNS @returnList TABLE(Id VARCHAR(5))
AS 
BEGIN
   DECLARE @splitValue VARCHAR(5)
   DECLARE @post INT

   WHILE CHARINDEX(';', @stringToSplit) > 0
   BEGIN 
       SELECT @pos = CHARINDEX(';', @stringToSplit)
       SELECT @splitValue = SUBSTRING(@stringToSplit, 1, @pos-1)
       INSERT INTO @returnList
       SELECT @splitValue
       SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit -@pos)
   END
   INSERT INTO @returnList
   SELECT @stringToSplit
   RETURN 
END

作為一個笑話(但它仍然有效):

WITH
cte1 AS ( SELECT id, ';'+value1+';' value1, value2, value3 
         FROM data ),
cte2 AS ( SELECT id, ';'+CAST(id AS VARCHAR)+';' sid, ';'+code+';' code
         FROM codevalue ),
cte3 AS ( SELECT cte1.id, REPLACE(cte1.value1, cte2.sid, cte2.code) value1, cte1.value2, cte1.value3, cte2.id cid
         FROM cte1 
         JOIN cte2 ON cte2.id = 0
       UNION ALL
         SELECT cte3.id, REPLACE(cte3.value1, cte2.sid, cte2.code) value1, cte3.value2, cte3.value3, cte2.id
         FROM cte3
         JOIN cte2 ON cte2.id = cte3.cid + 1 )
SELECT id, SUBSTRING(value1, 2, LEN(value1) - 2) value1, value2, value3 
FROM cte3
WHERE cid = ( SELECT MAX(id)
             FROM codevalue )
ORDER BY id

小提琴

需求CodeValue.id沒有差距。如果沒有,則添加 ROW_NUMBER() 列cte2並將其用於下一個程式碼值行選擇(不要忘記將靜態部分的起始值從 0 更改為 1)。

引用自:https://dba.stackexchange.com/questions/270658