多列上的SQL左联接返回部分匹配

时间:2020-04-28 11:55:38

标签: sql sql-server join left-join

我们目前使用查询表中的LEFT JOIN对数据进行验证,这些数据是在单个表上到单个列上,只是向一个表的普通左连接,然后我们在SELECT中执行case语句来说明是否返回值大于零(不为null),就可以,否则警告。当前流程如下所示:

SELECT

CASE WHEN LEN(C_Market.MCode) > 0 THEN 'Ok' ELSE 'Warning' END AS C_Market
CASE WHEN LEN(C_Language.LCode) > 0 THEN 'Ok' ELSE 'Warning' END AS C_Language

FROM [dbo].[CTable]

LEFT JOIN [dbo].[Lookup_Market] AS C_Market ON [dbo].CTable.[campaignNameMarket] = C_Market.MCode
LEFT JOIN [dbo].[Lookup_Language] AS C_Language ON [dbo].CTable.[campaignNameLanguage] = C_Language.LCode

我们想要做的是跨多个列进行验证,以便在我们的LEFT JOIN语句中添加AND。这将基于映射的查找表。我们的问题是,如果其中一列不匹配,则它将LEFT JOIN / AND中的所有列返回为NULL(这很有意义)。有没有一种方法可以执行多重连接,但如果它与LEFT JOIN / AND语句中的该列匹配,但仅在不匹配的列上返回NULL,仍然返回值?任何帮助将不胜感激

示例:

SELECT

CASE WHEN LEN(C_MarketLanguage.LCode) > 0 THEN 'Ok' ELSE 'Warning' END AS C_Language,
CASE WHEN LEN(C_MarketLanguage.MCode) > 0 THEN 'Ok' ELSE 'Warning' END AS C_Market

FROM [dbo].[CTable]

LEFT JOIN [dbo].[LookupMap_MarketLanguage] AS C_MarketLanguage ON [dbo].CTable.[campaignNameMarket] = C_MarketLanguage.MCode
AND [dbo].CTable.campaignNameLanguage = C_MarketLanguage.LCode

请参见下面的LookupMap_MarketLanguage表示例。在这里,我们将对MCode和LCode进行左连接。例如,假设主表将CH作为市场,将CZE作为语言。带有单独左联接的旧方法会说它们都不错,就像在每一列中一样,但是新的AND方法将两者都显示为警告。我希望Market显示为OK,但是Language显示为警告。

LookupMap_MarketLanguage Table
+----------------+-------+----------+-------+
|     Market     | MCode | Language | LCode |
+----------------+-------+----------+-------+
| Switzerland    | CH    | French   | FRE   |
| Switzerland    | CH    | German   | GER   |
| Czech Republic | CZ    | Czech    | CZE   |
| Germany        | DE    | German   | GER   |
+----------------+-------+----------+-------+
Sample CTable data
+--------------------+----------------------+
| campaignNameMarket | campaignNameLanguage |
+-------------------------------------------+
| DE                 | GER                  |
| CH                 | CZE                  |
| CZ                 | CZE                  |
+--------------------+----------------------+


Desired output
+----------+-------------+
| C_Market | C_Language  |
+----------+-------------+
| Ok       | Ok          |
| Ok       | Warning     |
| Ok       | Ok          |
+----------+-------------+
Current output with multiple left joins
+----------+-------------+
| C_Market | C_Language  |
+----------+-------------+
| Ok       | Ok          |
| Ok       | Ok          |
| Ok       | Ok          |
+----------+-------------+
Current output with AND LEFT JOIN
+----------+-------------+
| C_Market | C_Language  |
+----------+-------------+
| Ok       | Ok          |
| Warning  | Warning     |
| Ok       | Ok          |
+----------+-------------+

1 个答案:

答案 0 :(得分:0)

可能您可以使用存在查询而不是联接来执行此操作。即:

SELECT

CASE WHEN exists (select * 
from [dbo].[Lookup_Market] m 
where c.[campaignNameMarket] = C_Market.MCode and 
LEN(m.MCode) > 0
) THEN 'Ok' ELSE 'Warning' End as C_Market,

CASE WHEN exists (select * 
from [dbo].[dbo].[Lookup_Language] l 
where c.[campaignNameLanguage] =m.LCode and 
LEN(m.LCode) > 0
) THEN 'Ok' ELSE 'Warning' End as C_Language
FROM [dbo].[CTable] c;

编辑: 正如我之前所说,您的样本并不能涵盖所有情况,并且不会很有帮助。但是,至少现在比以前好了一点。如果那正是您想要的:

SELECT 
--     c.campaignNameMarket,
--     c.campaignNameLanguage,
       CASE
           WHEN EXISTS
                (
                    SELECT *
                    FROM dbo.LookupMap_MarketLanguage ml
                    WHERE c.campaignNameMarket = ml.MCode
                ) THEN 'Ok' ELSE 'Warning'
       END AS C_Market,
       CASE
           WHEN EXISTS
                (
                    SELECT *
                    FROM dbo.LookupMap_MarketLanguage ml
                    WHERE c.campaignNameMarket = ml.MCode
                          AND c.campaignNameLanguage = ml.LCode
                ) THEN 'Ok' ELSE 'Warning'
       END AS C_Language
FROM [dbo].[CTable] c;

您可以看到DBFiddle demo here.