SQL объединение таблиц и CASE с CONCAT - PullRequest
0 голосов
/ 01 мая 2020

Я SQL новичок ... и мне нужно объединить две таблицы (см. Ниже)

Table A
| id | Recipe_Web_Codes   |
|----|--------------------|
|  1 | GF VGT             |
|  2 |                    |
|  3 | VGN                |
Table B
| id | Recipe_Web_Code | Webcode_Fullname       | Color   |
|----|-----------------|------------------------|---------|
|  1 | VGT             | Vegetarian             | #ff6038 |
|  2 | VGN             | Vegan Friendly         | #97002d |
|  3 | GF              | Gluten Friendly        | #6ca4b6 |

и создать следующую таблицу:

RESULT
| id | Recipe_Web_Codes | Wecode_Fullname               | Color            |
|-------------------------------------------------------|------------------|
| 1  | GF VGT           | Gluten Friendly, Vegetarian   | #6ca4b6, #ff6038 |
| 2  |                  |                               |                  |
| 3  | VGN              | Vegan Friendly                | #97002d          |

Честно говоря, я не знаю, с чего начать. Я попробовал это, но застрял на том, как объединить результаты в одном поле. Я на правильном пути?

select Recipe_Web_Codes, Webcode_Fullname =  
    case 
        when Recipe_Web_Codes like '%VGT%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'VGT')
        when Recipe_Web_Codes like '%VGN%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'VGN')
        when Recipe_Web_Codes like '%GF%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'GF')
    end, 
    Color = 
    case 
        when Recipe_Web_Codes like '%VGT%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'VGT')
        when Recipe_Web_Codes like '%VGN%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'VGN')
        when Recipe_Web_Codes like '%GF%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'GF')
    end
from TABLE_A

РЕДАКТИРОВАТЬ: Мне просто щелкнуло, что я пропустил очень важный момент о том, почему мне нужно объединить эти строки. Полученная таблица будет экспортирована в JSON другим отдельным процессом, поэтому нет смысла упоминать нормализацию базы данных. Кроме того, это SQL 2016 SP2, поэтому у меня нет функции для String_agg.

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

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

Тем не менее, вы можете делать то, что вы хотите, разбирая строки и реагрегируя :

select a.*, b.*
from a outer apply
     (select string_agg(b.Webcode_Fullname, ',') as Webcode_Fullname,
             string_agg(b.Webcode_Fullname, ',') as Colors
      from string_split(a.recipe_web_codes, ' ') s join
           b
           on s.value = b.Recipe_Web_Code
     ) b;

Очень важно: string_split() не гарантирует порядок значений. Если упорядочение результирующих строк важно, вы можете справиться с этим - при условии, что у вас нет дубликатов - используя logi c, например:

select a.*, b.*
from a outer apply
     (select string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Webcode_Fullname,
             string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Colors
      from string_split(a.recipe_web_codes, ' ') s join
           b
           on s.value = b.Recipe_Web_Code
     ) b;

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

РЕДАКТИРОВАТЬ:

Одним из решений для более старых версий является рекурсивный CTE:

with bs as (
      select b.*, row_number() over (order by id) as seqnum
      from b
     ),
     cte as (
      select a.id, convert(varchar(max), Recipe_Web_Codes) as fullnames, convert(varchar(max), Recipe_Web_Codes)  as colors, 1 as ind
      from a
      union all
      select cte.id,
             replace(cte.fullnames, bs.Recipe_Web_Code, bs.Webcode_Fullname),
             replace(cte.colors, bs.Recipe_Web_Code, bs.color),
             1 + cte.ind
      from cte join
           bs
           on cte.ind = bs.seqnum and ind < 10
     )
select cte.id, cte.fullnames, cte.colors
from (select cte.*, max(ind) over (partition by id) as max_ind
      from cte
     ) cte
where ind = max_ind ;

Здесь - это дБ <> скрипка.

0 голосов
/ 01 мая 2020

Это можно сделать с помощью левого объединения таблиц и функции агрегирования string_agg() (работает в SQL Server 2017 +):

select a.id, a.Recipe_Web_Codes,
  string_agg(b.Webcode_Fullname, ', ') Webcode_Fullname,
  string_agg(b.Color, ', ') Color
from Table_A a left join Table_B b
on ' ' + a.Recipe_Web_Codes + ' ' like '% ' + b.Recipe_Web_Code + ' %'
group by a.id, a.Recipe_Web_Codes
order by a.id

См. демо . Результаты:

> id | Recipe_Web_Codes | Webcode_Fullname            | Color           
> -: | :--------------- | :-------------------------- | :---------------
>  1 | GF VGT           | Vegetarian, Gluten Friendly | #ff6038, #6ca4b6
>  2 | null             | null                        | null            
>  3 | VGN              | Vegan Friendly              | #97002d
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...