简体   繁体   English

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

[英]How do I split two columns in two separate tables into joined multiple rows in a view?

I have two separate tables, each containing character-separated cells. 我有两个单独的表,每个表包含字符分隔的单元格。 One table contains all the key data, the other all the val data. 一个表包含所有键数据,另一个表包含所有val数据。 In the application, both tables are loaded into recordsets, the two cells are split into two arrays and the arrays are then used 'side-by side' to create key/val pair. 在应用程序中,两个表都被加载到记录集中,两个单元格被拆分为两个数组,然后使用这些数组“并排”来创建键/值对。

Trying to decouple the database from the application, I will basically create a view that emulates this behavior. 试图从应用程序中分离数据库,我将基本上创建一个模拟此行为的视图。

I created some sample tables and data to better illustrate it. 我创建了一些示例表和数据以更好地说明它。

/* 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')

The desired end result in the view looks like this: 视图中所需的最终结果如下所示:

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

etc. 等等

I've seen similar questions here on StackOverflow, but they all deal with a single table being tilted in similar ways. 我在StackOverflow上看到过类似的问题,但是它们都处理以相似方式倾斜的单个表。 I need to tilt both tables while using the positions of the data in the two columns KeyData and ValData as siginficants when recombining them into proper key/val pairs. 当将它们重新组合成适当的键/值对时,我需要倾斜两个表,同时将两列KeyData和ValData中的数据位置用作标记。

How would I do this in an efficient manner? 我将如何有效地做到这一点?

[Edit]: The database design is not mine. [编辑]:数据库设计不是我的。 It's some old crap I inhereted. 这是我老套的东西。 I know it's bad. 知道这很糟糕。 Bad as in horrendous . 糟糕透顶

This would work for you. 这将为您工作。 But: you really should change your data design! 但是: 您确实应该更改数据设计!

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

The result 结果

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM