连接表,其中表名是另一个表中的值

时间:2019-03-05 10:12:13

标签: sql-server tsql

我的任务是从我设计的另一个数据库中获取一些数据,因此不能更改设计。

查看数据时,我需要根据另一个表中保存的值动态地连接一个表。

E.G

SELECT * FROM TableA LEFT JOIN TableB oN TableA.TBID = TableB.ID LEFT JOIN TableB.TableOffset AS C ON C.TableAID = TableA.ID

因此表B有一个名为TableOffset的列,其中包含需要作为C联接的表的名称。

(我尝试做一个SQLFIDDLE,但该站点无法与SQL Server ATM一起使用)

问题在于可能存在112个属性表,因此对它们中的每一个进行左联接都会降低查询速度。

因此,根据以下内容,我需要获得以下结果集:

| TableAID | TableATitle | AttrTableA21 | AttrTableA22 |
|----------|-------------|--------------|--------------|
|1         |test         | Name         | 2019         |
|2         |test2        | Name 2       | 2016         |

SQL代码示例

CREATE TABLE [dbo].[TableA](
  [ID] [int] NOT NULL,
  [Title] [nvarchar](100) NOT NULL,
  [TableBID] [int] NOT NULL
  );
CREATE TABLE [dbo].[TableB](
  [ID] [int] NOT NULL,
  [TableName] [nvarchar](100) NOT NULL
  );
CREATE TABLE [dbo].[ATTR_A](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_B](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_C](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_D](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );  
  INSERT INTO TableA VALUES(1, 'test', 1);
  INSERT INTO TableB VALUES(1, 'ATTR_C');
  INSERT INTO ATTR_C VALUES (1, 1, 'Name', 2019);
  INSERT INTO TableA VALUES(2, 'test2', 2);
  INSERT INTO TableB VALUES (2, 'ATTR_A');
  INSERT INTO ATTR_A VALUES (1, 2, 'Name 2', 2016);
    ```

1 个答案:

答案 0 :(得分:2)

您已经被告知,这种方法完全是错误的。但是,如果您必须坚持这样做,则可以尝试以下方法:

您在新数据库中的测试场景(认真,如果您已经使用此数据库名称...)

USE master;
GO
CREATE DATABASE MyTestDb;
GO
USE MyTestDb;
GO
CREATE TABLE [dbo].[TableA](
  [ID] [int] NOT NULL,
  [Title] [nvarchar](100) NOT NULL,
  [TableBID] [int] NOT NULL
  );
CREATE TABLE [dbo].[TableB](
  [ID] [int] NOT NULL,
  [TableName] [nvarchar](100) NOT NULL
  );
CREATE TABLE [dbo].[ATTR_A](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_B](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_C](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );
CREATE TABLE [dbo].[ATTR_D](
  [ID] [int] NOT NULL,
  [TableAID] [int] NOT NULL,
  [A21] [nvarchar](100) NOT NULL,
  [A22] [int] NOT NULL
  );  
  INSERT INTO TableA VALUES(1, 'test', 1);
  INSERT INTO TableB VALUES(1, 'ATTR_C');
  INSERT INTO ATTR_C VALUES (1, 1, 'Name', 2019);
  INSERT INTO TableA VALUES(2, 'test2', 2);
  INSERT INTO TableB VALUES (2, 'ATTR_A');
  INSERT INTO ATTR_A VALUES (1, 2, 'Name 2', 2016);
GO

-我创建了一个内联表值函数,其中所有属性表都使用UNION ALL作为一组返回。
-如果参数不合适,引擎足够聪明,可以避免调用。

CREATE FUNCTION dbo.GetTheRightSet(@SetKey VARCHAR(10))
RETURNS TABLE
AS
RETURN
    SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_A WHERE @SetKey='ATTR_A'
    UNION ALL
    SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_B WHERE @SetKey='ATTR_B'
    UNION ALL
    SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_C WHERE @SetKey='ATTR_C'
    UNION ALL
    SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_D WHERE @SetKey='ATTR_D'
GO

-这是使用方法

SELECT TableA.*
      ,TableB.*
      ,TheSet.* 
FROM TableA 
LEFT JOIN TableB ON TableA.TableBID = TableB.ID 
OUTER APPLY dbo.GetTheRightSet(TableB.TableName) TheSet
GO

-清理(仔细处理真实数据)

USE master;
GO
DROP DATABASE MyTestDb;