SQL левое соединение нескольких столбцов возвращает частичное совпадение - PullRequest
0 голосов
/ 28 апреля 2020

В настоящее время мы проводим проверку наших данных, используя LEFT JOIN из таблицы поиска, они для отдельных таблиц и отдельных столбцов, просто обычное левое соединение с одной таблицей, затем мы делаем оператор case в SELECT, чтобы сказать, возвращаемое ли значение больше нуля (не ноль), тогда все в порядке, иначе предупреждение. В настоящее время процесс выглядит следующим образом:

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

Мы стремимся выполнить проверку по нескольким столбцам, добавив AND к нашим операторам LEFT JOIN. Это будет основано на сопоставленных таблицах поиска. Наша проблема в том, что если один из столбцов не совпадает, он возвращает все столбцы в 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 был Market, а CZE - Language. Старый метод с отдельными левыми объединениями сказал бы, что они оба в порядке, как они есть в каждом столбце, однако новый метод AND будет показывать оба в качестве предупреждения. Я хотел бы, чтобы рынок отображался как ОК, а язык - как предупреждение.

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 голосов
/ 28 апреля 2020

Вероятно, вы могли бы вместо этого сделать это с существующим запросом, а не с объединениями. ie:

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 демо здесь.

...