Как объединить и суммировать случайные значения, разделенные запятыми, с помощью оператора case? - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть представление, которое является простым делом.

SELECT CAST(
         CASE 
              WHEN [value] = 'Canadian' and fieldid = 78
                 THEN 5
              WHEN [value] = 'US' and fieldid = 78
                 Then 3
              WHEN [value] = 'UK' and fieldid = 78
                 Then 1
              When [value] = 'Australia' and fieldid = 78
                 Then 1
              When [value] = 'Israel' and fieldid = 78
                 Then 1 
              When [value] = 'Others' and fieldid = 78
                 Then 1

Пока все в порядке, когда столбец имеет совпадающее значение, он дает ему точку, но иногда столбец может содержать несколько случайных значений, разделенных запятой. Как я могу рассчитать это? Это то, что происходит сейчас.

 +----+------------------+--------+
 | ID | Value            | Points |
 +----+------------------+--------+
 |  1 | Canadian         |   5    |
 |  2 | UK               |   1    |
 |  3 | Canadian,UK      |   0    |
 +----+----------+----------------+

Ожидаемый результат

 +----+------------------+--------+
 | ID | Value            | Points |
 +----+------------------+--------+
 |  1 | Canadian         |   5    |
 |  2 | UK               |   1    |
 |  3 | Canadian,UK      |   6    |
 +----+----------+----------------+

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Вы можете сделать это только с CASE и LIKE:

SELECT ((CASE WHEN ',' + [value] + ',' LIKE '%,Canadian,%' and fieldid = 78
             THEN 5 ELSE 0
         END) +
        (CASE WHEN ',' + [value] + ',' LIKE '%,US,%' and fieldid = 78
             THEN 3 ELSE 0
         END) +
        (CASE WHEN ',' + [value] + ',' LIKE '%,UK,%' and fieldid = 78
             THEN 1 ELSE 0
         END) +
        (CASE WHEN ',' + [value] + ',' LIKE '%,Australia,%' and fieldid = 78
             THEN 1 ELSE 0
         END) +
        (CASE WHEN ',' + [value] + ',' LIKE '%,Israel,%' and fieldid = 78
             THEN 1 ELSE 0
         END) +
        (CASE WHEN ',' + [value] + ',' LIKE '%,Others,%' and fieldid = 78
             THEN 1 ELSE 0
         END)
       ) as val

Тем не менее я настоятельно, настоятельно рекомендую вам не хранить несколько значений в одном столбце. SQL предназначен для хранения одного значения в столбцах (по крайней мере для скалярных типов столбцов, а строка - скалярного типа).

У вас должна быть отдельная таблица, представляющая собой таблицу соединений / связей с одной строкой для каждой сущности и страны.

РЕДАКТИРОВАТЬ: Если вы использовали SQL Server 2017 или у вас была функция разделения строки, я бы посоветовал вам сделать это следующим образом:

SELECT t.ID, t.[value], COALESCE(s.points, 0) as points
FROM tab t OUTER APPLY
     (SELECT SUM(CASE WHEN s.[value] = 'Canadian' THEN 5
                      WHEN s.[value] = 'US' THEN 3
                      WHEN s.[value] IN ('UK', 'Australia' , 'Israel', 'Others') THEN 1
                 END) AS Points
      FROM STRING_SPLIT(t.[value], ',') s
      WHERE t.fieldid = 78
     ) s
ORDER BY t.id;
0 голосов
/ 29 апреля 2018

Начиная с SQL Server 2017 вы можете использовать:

SELECT DISTINCT t.ID, t.[value],
         SUM(CASE 
              WHEN s.[value] = 'Canadian' and fieldid = 78
                 THEN 5
              WHEN s.[value] = 'US' and fieldid = 78
                 Then 3
              WHEN s.[value] = 'UK' and fieldid = 78
                 Then 1
              When s.[value] = 'Australia' and fieldid = 78
                 Then 1
              When s.[value] = 'Israel' and fieldid = 78
                 Then 1 
              When s.[value] = 'Others' and fieldid = 78
                 Then 1
           END) OVER(PARTITION BY ID) AS Points
FROM tab t
CROSS APPLY STRING_SPLIT(t.[value], ',') s
ORDER BY t.id;

Демоверсия DBFiddle

Хранение нескольких значений в одном столбце нарушает первую нормальную форму, и этого следует избегать.


Это может быть упрощено до:

SELECT DISTINCT t.ID, t.[value],
             SUM(CASE 
                  WHEN s.[value] = 'Canadian' and fieldid = 78
                     THEN 5
                  WHEN s.[value] = 'US' and fieldid = 78
                     Then 3
                  WHEN s.[value] IN ('UK', 'Australia' , 'Israel', 'Others') 
                       and fieldid = 78
                     Then 1
               END) OVER(PARTITION BY ID) AS Points
FROM tab t
CROSS APPLY STRING_SPLIT(t.[value], ',') s
ORDER BY t.id;
...