【问题标题】:Join multiple tables with ?optional? conditions and get all results使用 ?optional? 加入多个表条件并获得所有结果
【发布时间】:2017-01-16 20:21:34
【问题描述】:

使用 SQL 2008 R2

我无法完成表连接。我想我只是缺少一些简单的东西。我需要加入三个表(CMS、DB、备份)并获得所有重叠和缺失项目的完整列表。不幸的是,其中两个表没有简单的条件来进行连接。

条件:
1:每个表都可以有一行与其他表不匹配
2:备份加入 Server_Name 和 Backups.Save_Set 就像 DB.Instance_Name 或 Backups.Save_Set 就像 'ALL'
3:CMS 加入 Server_Name 和 CMS.Name 就像 DB.Name

您可以从下面的查询结果中看到,我很接近,但并不完全在那里。我似乎无法正确连接前两行或我的结果,因为它们不符合条件。

任何帮助将不胜感激。我似乎找不到我缺少的东西。

在底部创建/填充脚本

表:数据库

ID    Server_Name      Instance_Name        Name        Company_Code
----- ---------------- -------------------- ----------- --------------------
1     Server11         MSSQLSERVER          PUB         14
2     Server11         MSSQLSERVER          Test        10
3     Server11         MSSQLSERVER          fasys       14
4     Server12         MSSQLSERVER          PROD        14
5     Server21         MSSQLSERVER          PROD        24

表:CMS

ID          Name                     Server_Name          Responsible
----------- ------------------------ -------------------- ---------------
1           Site1 SQL DB PUB         Server11             PDM
2           Site1 SQL DB Test        Server11             RH
3           Site1 SQL DB PROD        Server12             PDM
4           Site2 SQL DB PROD        Server21             SP
5           Site2 SQL DB Test        Server21             PDM

表:备份

ID     Server_Name     Backup_Retention     Save_Set
------ --------------- -------------------- ---------------------
1      Server11        3Month               MSSQL$MSSQLSERVER
2      Server11        3Month               MSSQL$ECS
3      Server12        3Month               ALL
4      Server22        3Month               ALL

我接近了:

SELECT AllNames.Server_Name
      ,CMS.Name
      ,CMS.Responsible
      ,DB.Instance_Name
      ,DB.Name
      ,DB.Company_Code
      ,B.Backup_Retention
      ,B.Save_Set
FROM (SELECT Server_Name FROM CMS
    UNION
    SELECT Server_Name FROM DB
    UNION
    SELECT Server_Name FROM Backups) AllNames
LEFT JOIN DB ON AllNames.Server_Name = DB.Server_Name
FULL JOIN Backups B ON AllNames.Server_Name = B.Server_Name
                                  AND ((B.Save_Set LIKE '%' + DB.Instance_Name OR DB.Instance_Name IS NULL) OR B.Save_Set LIKE 'ALL')
FULL JOIN CMS ON AllNames.Server_Name = CMS.Server_Name
                                 AND CMS.Name LIKE '%' + DB.Name
ORDER BY AllNames.Server_Name ASC

返回:

Server_Name   Name                Responsible   Instance_Name   Name    Company_Code   Backup_Retention   Save_Set
------------- ------------------- ------------- --------------- ------- -------------- ------------------ -------------------
NULL          NULL                NULL          NULL            NULL    NULL           3Month             MSSQL$ECS
NULL          Site2 SQL DB Test   PDM           NULL            NULL    NULL           NULL               NULL
Server11      Site1 SQL DB PUB    PDM           MSSQLSERVER     PUB     14             3Month             MSSQL$MSSQLSERVER
Server11      Site1 SQL DB Test   RH            MSSQLSERVER     Test    10             3Month             MSSQL$MSSQLSERVER
Server11      NULL                NULL          MSSQLSERVER     fasys   14             3Month             MSSQL$MSSQLSERVER
Server12      Site1 SQL DB PROD   PDM           MSSQLSERVER     PROD    14             3Month             ALL
Server21      Site2 SQL DB PROD   SP            MSSQLSERVER     PROD    24             NULL               NULL
Server22      NULL                NULL          NULL            NULL    NULL           3Month             ALL

我想看到的(不用担心列标题):

Server_Name   CMS.Name            CMS.Responsible  DB.Instance_Name  DB.Name  DB.Company_Code  Backups.Backup_Retention  Backups.Save_Set
------------  ------------------  ---------------- ----------------- -------- ---------------- ------------------------- -----------------
Server11      Site1 SQL DB PUB    PDM              MSSQLSERVER       PUB      14               3Month                    MSSQL$MSSQLSERVER
Server11      Site1 SQL DB Test   RH               MSSQLSERVER       Test     10               3Month                    MSSQL$MSSQLSERVER
Server11      NULL                NULL             MSSQLSERVER       fasys    14               3Month                    MSSQL$MSSQLSERVER
Server11      NULL                NULL             NULL              NULL     NULL             3Month                    MSSQL$ECS
Server12      Site1 SQL DB PROD   PDM              MSSQLSERVER       PROD     14               3Month                    ALL
Server21      Site2 SQL DB PROD   SP               MSSQLSERVER       PROD     24               NULL                      NULL
Server21      Site2 SQL DB Test   PDM              NULL              NULL     NULL             NULL                      NULL
Server22      NULL                NULL             NULL              NULL     NULL             3Month                    ALL

创建/填充:

CREATE TABLE CMS(
   ID int  NOT NULL IDENTITY(1, 1),
   Name nvarchar(60)  NOT NULL,
   Server_Name nvarchar(20)  NOT NULL,
   Responsible nvarchar(20)  NULL
   CONSTRAINT CMS_DB_Audit_pk PRIMARY KEY  (ID)
);

CREATE TABLE DB(
   ID int  NOT NULL IDENTITY(1, 1),
   Server_Name nvarchar(20)  NOT NULL,
   Instance_Name nvarchar(20) NOT NULL,
   Name nvarchar(60)  NOT NULL,
   Company_Code nvarchar(20)  NULL
   CONSTRAINT DB_pk PRIMARY KEY  (ID)
);

CREATE TABLE Backups (
   ID int  NOT NULL IDENTITY(1, 1),
   Server_Name nvarchar(30)  NOT NULL,
   Backup_Retention nvarchar(20)  NOT NULL,
   Save_Set nvarchar(max)  NOT NULL,
   CONSTRAINT Backups_pk PRIMARY KEY  (ID)
);

INSERT INTO CMS
VALUES 
('Site1 SQL DB PUB','Server11','PDM'),
('Site1 SQL DB Test','Server11','RH'),
('Site1 SQL DB PROD','Server12','PDM'),
('Site2 SQL DB PROD','Server21','SP'),
('Site2 SQL DB Test','Server21','PDM');

INSERT INTO DB
VALUES 
('Server11','MSSQLSERVER','PUB',14),
('Server11','MSSQLSERVER','Test',10),
('Server11','MSSQLSERVER','fasys',14),
('Server12','MSSQLSERVER','PROD',14),
('Server21','MSSQLSERVER','PROD',24);

INSERT INTO Backups
VALUES 
('Server11','3Month','MSSQL$MSSQLSERVER'),
('Server11','3Month','MSSQL$ECS'),
('Server12','3Month','ALL'),
('Server22','3Month','ALL');

【问题讨论】:

  • 嗨约瑟夫,这是一个好问题!您提供了一个好问题所需的一切,感谢您和 +1

标签: sql sql-server sql-server-2008 join


【解决方案1】:

这对你有用吗?

SELECT coalesce(DB.Server_Name, b.Server_Name, CMS.Server_Name) Server_Name
      ,CMS.Name
      ,CMS.Responsible
      ,DB.Instance_Name
      ,DB.Name
      ,DB.Company_Code
      ,B.Backup_Retention
      ,B.Save_Set
FROM #DB DB --ON AllNames.Server_Name = DB.Server_Name
FULL JOIN #Backups B ON DB.Server_Name = B.Server_Name
                                  AND ((B.Save_Set LIKE '%' + DB.Instance_Name /*OR DB.Instance_Name IS NULL*/) OR B.Save_Set LIKE 'ALL')
FULL JOIN #CMS CMS ON DB.Server_Name = CMS.Server_Name
                                 AND CMS.Name LIKE '%' + DB.Name
ORDER BY coalesce(DB.Server_Name, b.Server_Name, CMS.Server_Name) ASC

它会给出结果

Server_Name Name    Responsible Instance_Name   Name    Company_Code    Backup_Retention    Save_Set
Server11    Site1 SQL DB PUB    PDM MSSQLSERVER PUB 14  3Month  MSSQL$MSSQLSERVER
Server11    Site1 SQL DB Test   RH  MSSQLSERVER Test    10  3Month  MSSQL$MSSQLSERVER
Server11    NULL    NULL    MSSQLSERVER fasys   14  3Month  MSSQL$MSSQLSERVER
Server11    NULL    NULL    NULL    NULL    NULL    3Month  MSSQL$ECS
Server12    Site1 SQL DB PROD   PDM MSSQLSERVER PROD    14  3Month  ALL
Server21    Site2 SQL DB PROD   SP  MSSQLSERVER PROD    24  NULL    NULL
Server21    Site2 SQL DB Test   PDM NULL    NULL    NULL    NULL    NULL
Server22    NULL    NULL    NULL    NULL    NULL    3Month  ALL

【讨论】:

  • 两种解决方案都能完美运行,但这个解决方案让我可以简化脚本中的其他一些事情,而且更直接一些。感谢您的帮助!
【解决方案2】:

你已经很接近了:

试试这个:

WITH AllServers AS
(
    SELECT DISTINCT Server_Name FROM DB 
    UNION SELECT Server_Name FROM CMS
    UNION SELECT Server_Name FROM Backups
)
SELECT COALESCE(AllServers.Server_Name,DB.Server_Name,CMS.Server_Name,Backups.Server_Name) AS Server_Name
      ,CMS.Name AS CMS_Name
      ,CMS.Responsible AS CMS_Responsible
      ,DB.Instance_Name AS DB_InstanceName
      ,DB.Name AS [DB_Name]
      ,DB.Company_Code AS DB_CompanyCode
      ,Backups.Backup_Retention
      ,Backups.Save_Set
FROM AllServers
FULL OUTER JOIN DB ON AllServers.Server_Name=DB.Server_Name 
FULL OUTER JOIN Backups ON AllServers.Server_Name=Backups.Server_Name AND (Backups.Save_Set LIKE '%' + DB.Instance_Name OR Backups.Save_Set='ALL')
FULL OUTER JOIN CMS ON AllServers.Server_Name=CMS.Server_Name AND CMS.Name LIKE '%' + DB.Name
ORDER BY COALESCE(AllServers.Server_Name,DB.Server_Name,CMS.Server_Name,Backups.Server_Name)

更新:试图找出差异...

我认为,如果您只在第一行使用我的COALESCE(AllNames.Server_Name,DB.Server_Name,CMS.Server_Name,B.Server_Name) 并作为ORDER BY...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    相关资源
    最近更新 更多