Sql 如何将两个单独表中的两列拆分为视图中的多行?

Sql 如何将两个单独表中的两列拆分为视图中的多行?,sql,sql-server,tsql,split,sql-server-2012,Sql,Sql Server,Tsql,Split,Sql Server 2012,我有两个单独的表,每个表包含字符分隔的单元格。一个表包含所有键数据,另一个表包含所有val数据。在应用程序中,两个表都加载到记录集中,两个单元格被拆分为两个数组,然后这些数组“并排”用于创建键/值对 尝试将数据库与应用程序分离,我将基本上创建一个模拟此行为的视图 我创建了一些示例表和数据来更好地说明它 /* Create tables */ CREATE TABLE [dbo].[tblKeys]( [KeyId] [int] NOT NULL, /*PK*/ [KeyData]

我有两个单独的表,每个表包含字符分隔的单元格。一个表包含所有键数据,另一个表包含所有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中的数据位置用作siginficant,以便将它们重新组合为正确的键/值对

我将如何以有效的方式进行此操作


[编辑]:数据库设计不是我的。这是我的一些旧垃圾。我知道这很糟糕。就像在恐怖中一样糟糕。

这对你有用。但是:你真的应该改变你的数据设计

;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.

不要像|分隔项那样存储数据。这只会给你带来很多麻烦。(正如你今天可能已经注意到的……我知道。这是我无法控制的遗留垃圾。我正在努力让它能够承受。我自己从来没有这样做过。顺便说一句:Thx对于可复制粘贴的测试场景和预期输出。值得一提如果你想要一个答案,那么提供最好的输入是件好事。如果需要帮助,请确保帮助者能够关注实际问题,而不是设置。:-)是-数据库设计是垃圾。但不是我的电话。这是我加入该公司之前的一款非常古老的自制咖啡。最初的数据库“设计者”似乎对数据库设计一无所知。通过分析数据库设计,我猜它起源于一些业务经理Excel电子表格,刚刚被移植到SQL Server中。@CBDuRietz,可怜的家伙:-)这种“遗留垃圾”可能是个噩梦。。。我将编辑我的答案,在
行编号()中添加一个
分区(按KeyId,Language
,我应该指出,所涉及的原始表更糟糕。我在问题中提出的问题经过了净化和简化,以专注于手头的问题。:-)@祝你好运和快乐!如果你喜欢我的答案,请投票表决,如果它解决了你的问题,请-另外标记为接受答案,谢谢!看起来很有魅力。不过,在将其标记为可接受答案之前,我将尝试将其移植回真实的数据库。我可能还有一两个问题要问。数据库是一个雷区。
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
 [...]