简体   繁体   English

SQL查询根据映射动态获取列

[英]SQL Query Dynamically get columns depending on mapping

I am stuck on an issue.我被困在一个问题上。 I am trying to create a select which returns information depending on the Rules Mapping table.我正在尝试创建一个根据规则映射表返回信息的选择。 The Rules table tells us where (TableName.ColumnName) value should come from.规则表告诉我们 (TableName.ColumnName) 值应该从哪里来。 I have simplified the problem by just creating table variables to find a solution.我通过创建表变量来找到解决方案来简化问题。

I have 3 tables set up.我设置了 3 个表。

  1. @TableA which contains the Main_ID. @TableA 其中包含 Main_ID。 First Table.第一张桌子。
  2. @TableB which contains more information for the Main_ID. @TableB 其中包含有关 Main_ID 的更多信息。 Second table.第二张桌子。
  3. @Rules is the mapping table. @Rules 是映射表。 It has headers for what the final select should have and also tells us where the the data should come from (What table and column).它有最终选择应该有的标题,还告诉我们数据应该来自哪里(什么表和列)。

在此处输入图像描述

The final expected result I am trying to achieve is this with the above rules is:我试图通过上述规则达到的最终预期结果是:

在此处输入图像描述

As you can see, I will have 3 columns in total with 3 rows (as I have 3 Main_ID).如您所见,我总共有 3 列 3 行(因为我有 3 个 Main_ID)。 Data differs depending on the @Rules table.数据因@Rules 表而异。 For example, Header C for Main_ID 3 is showing "Address C" as the rule mapping for Header C Main_ID 3 was "@TableB.Address" which means get the information from table @TableB and column Address.例如,Main_ID 3 的 Header C 显示“地址 C”,因为 Header C Main_ID 3 的规则映射是“@TableB.Address”,这意味着从表 @TableB 和列地址获取信息。

Here is my code for the table set up:这是我设置表格的代码:

DECLARE @TableA AS TABLE
(
    Main_ID INT IDENTITY(1, 1) ,
    Name VARCHAR(100)
)

INSERT INTO @TableA
VALUES ('Name A'), ('Name B'), ('Name C')

DECLARE @TableB AS TABLE
(
    Secondary_ID INT IDENTITY(1, 1) ,
    Main_ID INT ,
    Address VARCHAR(100)
)

INSERT INTO @TableB
VALUES (1, 'Address A'), (2, 'Address B'), (3, 'Address C')

DECLARE @Rules AS TABLE
(
    Rule_ID INT IDENTITY(1, 1) ,
    Main_ID INT ,
    Header_Name VARCHAR(100) ,
    Obtain_From VARCHAR(100) 
)

INSERT INTO @Rules
VALUES 
-- Main_ID 1 AND 2 set up same but third one wants data from a different place.
(1, 'Header A', '@TableA.Main_ID'), (1, 'Header B', '@TableB.Address'), (1, 'Header C', '@TableA.Name'),
(2, 'Header A', '@TableA.Main_ID'), (2, 'Header B', '@TableB.Address'), (2, 'Header C', '@TableA.Name'),
(3, 'Header A', '@TableA.Main_ID'), (3, 'Header B', '@TableA.Name'), (3, 'Header C', '@TableB.Address')

SELECT * FROM @TableA
SELECT * FROM @TableB
SELECT * FROM @Rules

/*
    Final result set should be:
    Header A        Header B        Header C
    1               Address A       Name A
    2               Address B       Name B
    3               Name C          Address C       
*/

What I have tried so far is joining the table together but there are too many rows.到目前为止,我尝试过的是将表格连接在一起,但行数太多。

在此处输入图像描述 在此处输入图像描述

Any ideas how I can achieve the final expected result?我有什么想法可以达到最终的预期结果吗?

There is a two way to do it.有两种方法可以做到。

The first way is static and easy.第一种方式是静态的并且简单。 You can use CASE expression for your mapping like that:您可以像这样使用 CASE 表达式进行映射:

SELECT
    [Header A]  = CASE r_headera.Obtain_From WHEN '@TableA.Main_ID' THEN CAST(a.Main_ID AS NVARCHAR(100)) WHEN '@TableA.Name' THEN CAST(a.Name AS NVARCHAR(100)) WHEN '@TableB.Address' THEN CAST(b.Address AS NVARCHAR(100)) END,
    [Header B]  = CASE r_headerb.Obtain_From WHEN '@TableA.Main_ID' THEN CAST(a.Main_ID AS NVARCHAR(100)) WHEN '@TableA.Name' THEN CAST(a.Name AS NVARCHAR(100)) WHEN '@TableB.Address' THEN CAST(b.Address AS NVARCHAR(100)) END,
    [Header C]  = CASE r_headerc.Obtain_From WHEN '@TableA.Main_ID' THEN CAST(a.Main_ID AS NVARCHAR(100)) WHEN '@TableA.Name' THEN CAST(a.Name AS NVARCHAR(100)) WHEN '@TableB.Address' THEN CAST(b.Address AS NVARCHAR(100)) END
FROM
    @TableA AS a
    LEFT JOIN @TableB AS b ON b.Main_ID = a.Main_ID
    LEFT JOIN @Rules AS r_headera ON r_headera.Main_ID = a.Main_ID AND r_headera.Header_Name = 'Header A'
    LEFT JOIN @Rules AS r_headerb ON r_headerb.Main_ID = a.Main_ID AND r_headerb.Header_Name = 'Header B'
    LEFT JOIN @Rules AS r_headerc ON r_headerc.Main_ID = a.Main_ID AND r_headerc.Header_Name = 'Header C'

Otherwise, you can use other structs such as Table Value Constructor , PIVOT , OUTER APPLY etc.否则,您可以使用其他结构,例如Table Value ConstructorPIVOTOUTER APPLY等。

The result:结果:

Header A标头A Header B标头 B Header C标题 C
1 1个 Address A地址A Name A名称 A
2 2个 Address B地址B Name B名称乙
3 3个 Name C名称 C Address C地址C

And the second way is Dynamic SQL with sp_executesql .第二种方法是使用sp_executesql的动态 SQL。 If you need help with that, I can prepare an example for you.如果您需要这方面的帮助,我可以为您准备一个示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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