[英]How do I split two columns in two separate tables into joined multiple rows in a view?
我有兩個單獨的表,每個表包含字符分隔的單元格。 一個表包含所有鍵數據,另一個表包含所有val數據。 在應用程序中,兩個表都被加載到記錄集中,兩個單元格被拆分為兩個數組,然后使用這些數組“並排”來創建鍵/值對。
試圖從應用程序中分離數據庫,我將基本上創建一個模擬此行為的視圖。
我創建了一些示例表和數據以更好地說明它。
/* Create tables */
CREATE TABLE [dbo].[tblKeys](
[KeyId] [int] NOT NULL, /*PK*/
[KeyData] [nvarchar](max) NULL
)
CREATE TABLE [dbo].[tblValues](
[ValId] [int] NOT NULL, /*PK*/
[KeyId] [int] NOT NULL, /*FK*/
[Language] [nvarchar](5) NOT NULL,
[ValData] [nvarchar](max) NULL
)
/* Populate tables */
INSERT INTO [dbo].[tblKeys] ([KeyId], [KeyData]) VALUES
(1, '1|2|3'),
(2, '1|2|3|4'),
(3, '2|1')
INSERT INTO [dbo].[tblValues] ([ValId], [KeyId], [Language], [ValData]) VALUES
(1, 1, 'en', 'Apple|Orange|Pear'),
(2, 1, 'sv-se', 'Äpple|Apelsin|Päron'),
(3, 2, 'en', 'Milk|Butter|Cheese|Cream'),
(4, 2, 'sv-se', 'Mjölk|Smör|Ost|Grädde'),
(5, 3, 'en', 'Male|Female'),
(6, 3, 'sv-se', 'Man|Kvinna')
視圖中所需的最終結果如下所示:
| KeyId | KeyData | Language | ValData
+-------+---------+----------+----------+
| 1 | 1 | en | Apple |
| 1 | 2 | en | Orange |
| 1 | 3 | en | Pear |
| 1 | 1 | sv-se | Äpple |
| 1 | 2 | sv-se | Apelsin |
| 1 | 3 | sv-se | Päron |
...
等等
我在StackOverflow上看到過類似的問題,但是它們都處理以相似方式傾斜的單個表。 當將它們重新組合成適當的鍵/值對時,我需要傾斜兩個表,同時將兩列KeyData和ValData中的數據位置用作標記。
我將如何有效地做到這一點?
[編輯]:數據庫設計不是我的。 這是我老套的東西。 我知道這很糟糕。 糟糕透頂 。
這將為您工作。 但是: 您確實應該更改數據設計!
;WITH Splitted AS
(
SELECT v.Language
,v.ValData
,v.ValId
,k.KeyData
,k.KeyId
,CAST('<x>' + REPLACE(v.ValData,'|','</x><x>') + '</x>' AS XML) AS ValData_XML
,CAST('<x>' + REPLACE(k.KeyData,'|','</x><x>') + '</x>' AS XML) AS KeyData_XML
FROM tblValues AS v
INNER JOIN tblKeys AS k ON v.KeyId=k.KeyId
)
,NumberedValData AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY KeyId,Language ORDER BY (SELECT NULL)) AS RowNumber
,KeyId
,Language
,A.B.value('.','varchar(max)') AS ValD
FROM Splitted
CROSS APPLY Splitted.ValData_XML.nodes('/x') AS A(B)
)
,NumberedKeyData AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY KeyId,Language ORDER BY (SELECT NULL)) AS RowNumber
,KeyId
,Language
,A.B.value('.','varchar(max)') AS KeyD
FROM Splitted
CROSS APPLY Splitted.KeyData_XML.nodes('/x') AS A(B)
)
,Combined AS
(
SELECT nk.KeyId
,nk.KeyD
,nk.Language
,nv.ValD
FROM NumberedKeyData AS nk
INNER JOIN NumberedValData AS nv ON nk.KeyId=nv.KeyId AND nk.Language=nv.Language AND nk.RowNumber=nv.RowNumber
)
SELECT Combined.KeyId
,Combined.KeyD AS KeyData
,Splitted.Language
,Combined.ValD AS ValData
FROM Splitted
INNER JOIN Combined ON Splitted.KeyId=Combined.KeyId AND Splitted.Language=Combined.Language
ORDER BY Splitted.KeyId,Splitted.
結果
KeyId KeyData Language ValData
1 1 en Apple
1 2 en Orange
1 3 en Pear
1 1 sv-se Äpple
1 2 sv-se Apelsin
1 3 sv-se Päron
2 1 en Milk
2 2 en Butter
[...]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.