SQL Server — сравнение значений из одной и той же таблицы

#sql #sql-server

#sql #sql-сервер

Вопрос:

В SQL Server у меня есть одна таблица со следующими данными (tblUserSettings):

 | CountryID | CityID  | UserType | Value1 | Value2 | Value3 |
| 9         | 3       | 1        | 5      | 5      | 5      |
| 9         | 3       | 2        | NULL   | NULL   | NULL   |
| 9         | 3       | 3        | 5      | 5      | 5      |
| 9         | 3       | 4        | 5      | 5      | 5      |
| 9         | 20      | 1        | 5      | 5      | 5      |
| 9         | 20      | 2        | NULL   | NULL   | NULL   |
| 9         | 20      | 3        | 5      | 5      | 5      |
| 9         | 20      | 4        | 0      | 0      | 0      |
  

Мне нужно сравнить все значения для всех типов пользователей из CityId = 20 со всеми значениями для соответствующих типов пользователей из CityId = 3. Идентификатор страны = 9. Сравниваемые столбцы: Значение1, Значение2, Значение3.

Мне просто нужно знать, все ли они сопоставлены друг с другом или нет. Я попытался сделать что-то следующим образом:

 SELECT CASE WHEN ISNULL(t1.Value1, 0) = ISNULL(t2.Value1, 0) THEN 1 ELSE 0 END AS Match1,
        CASE WHEN ISNULL(t1.Value2, 0) = ISNULL(t2.Value2, 0) THEN 1 ELSE 0 END AS Match2,
        CASE WHEN ISNULL(t1.Value3, 0) = ISNULL(t2.Value3, 0) THEN 1 ELSE 0 END AS Match3
FROM tblUserSettings t1
INNER JOIN tblUserSettings t2 ON t1.CountryID = t2.CountryID 
           AND t1.UserType = t2.UserType
           AND t1.CityID = 3
           AND t2.CityID = 20
WHERE t1.CountryID = 9
  

И это дает мне следующий результат, который я должен обработать дальше, чтобы определить, все ли совпадает или нет.

 | Match1 | Match2  | Match3 |
| 1      | 1       | 1      |
| 1      | 1       | 1      |
| 1      | 1       | 1      |
| 0      | 0       | 0      |
  

Могу ли я сделать это таким образом, чтобы на выходе был только один столбец и строка — просто получите либо 1 для всех совпадений, либо 0, если хотя бы одно не совпадает?

Комментарии:

1. как должен выглядеть результат?

Ответ №1:

Если вы хотите получить только один столбец, 1 когда все значения совпадают, и 0 если хотя бы одно из них не совпадает, используйте,

 SELECT 
CASE WHEN ISNULL(t1.Value1, 0) = ISNULL(t2.Value1, 0) 
      AND ISNULL(t1.Value2, 0) = ISNULL(t2.Value2, 0) 
      AND ISNULL(t1.Value3, 0) = ISNULL(t2.Value3, 0) 
THEN 1 ELSE 0 END AS Match
FROM tblUserSettings t1
INNER JOIN tblUserSettings t2 ON t1.CountryID = t2.CountryID 
           AND t1.UserType = t2.UserType
           AND t1.CityID = 3
           AND t2.CityID = 20
WHERE t1.CountryID = 9
  

Комментарии:

1. Да, это именно то, что я ищу.

2. На самом деле, он по-прежнему дает мне 4 строки для каждого типа пользователя. Я изменил этот запрос и добавил SUM() перед РЕГИСТРОМ, чтобы на выходе была только 1 строка.

3. функция sum() не требуется. Просто используйте distinct .

4. Да, но если я использую distinct, то, если есть некоторые различия в UserType, будет две строки вместо одной. (одно с 1, а другое с 0)

5. Для usertype 4 значения не совпадают. Поэтому для этой строки должно быть 0. Если вы подведете итог, это будет 1, что означает, что все значения совпадают, а это не то, что вам нужно, я думаю.

Ответ №2:

Если вы хотите сравнить все города, а не только два, вы должны быть в состоянии сделать это путем группировки, а не объединения.

Что-то вроде:

 SELECT 
CASE WHEN
       max(Value1)-min(Value1) = 0
       AND max(Value2)-min(Value2) = 0
       AND max(Value3)-min(Value3) = 0
THEN 1 ELSE 0 AS Match
FROM tblUserSettings
GROUP BY CountryID,UserType