SQL Сервер JSON массив значений внешних ключей с использованием объединения - PullRequest
1 голос
/ 12 марта 2020

Ниже приведена схема данных, хранящихся в SQL База данных Server 2016

+------------+-------------+
| CountryKey | CountryName |
+------------+-------------+
|          1 | USA         |
|          2 | Japan       |
|          3 | China       |
|          4 | UK          |
|          5 | Australia   |
+------------+-------------+

. И в таблице Store информация сохраняется как JSON

+-------+-----------+
| Store | Countries |
+-------+-----------+
| A     | [1,2]     |
| B     | [1,3]     |
| C     | [1,3,4]   |
| D     | [4,5]     |
| E     | [1,5]     |
+-------+-----------+

Этот дизайн работает нормально, когда я хочу фильтровать данные, например, я могу использовать OPEN_ JSON для фильтрации хранилищ на основе CountryKey

Но после фильтрации - требование чтобы показать Country Name вместо ключа страны, как показано ниже -

Желаемый результат

+-------+----------------+
| Store | CountriesName  |
+-------+----------------+
| A     | USA, Japan     |
| B     | USA, China     |
| C     | USA, China, UK |
| D     | UK, Asutralia  |
| E     | USA, Australia |
+-------+----------------+

Мой вопрос - может ли это быть достигнуто с помощью SQL Query или необходимо обрабатывать данные на языке сервера, например C#. Если да, то синтаксис и ссылки помогут.

1 Ответ

2 голосов
/ 12 марта 2020

Одним из возможных решений является синтаксический анализ кода страны с помощью OPENJSON(), использование соответствующего объединения и агрегирование названий стран. Для SQL Server 2016 вам нужно использовать FOR XML PATH для агрегирования строк:

Таблицы:

CREATE TABLE Country (
   CountryKey int,
   CountryName nvarchar(100)
)
INSERT INTO Country 
   (CountryKey, CountryName)
VALUES
   (1, N'USA'),
   (2, N'Japan'),   
   (3, N'China'),   
   (4, N'UK'),      
   (5, N'Australia')
CREATE TABLE Store (
   Store nvarchar(1),
   Countries nvarchar(max)
)
INSERT INTO Store
   (Store, Countries)
VALUES   
   (N'A', N'[1,2]'),
   (N'B', N'[1,3]'),
   (N'C', N'[1,3,4]'),
   (N'D', N'[4,5]'),
   (N'E', N'[1,5]')

Оператор:

SELECT s.Store, STUFF(t.Country, 1, 2, N'') AS Country
FROM Store s
CROSS APPLY (
   SELECT ', ' + c.CountryName
   FROM OPENJSON(s.Countries) WITH (CountryKey int '$') j
   LEFT JOIN Country c ON c.CountryKey = j.CountryKey
   FOR XML PATH('')
) t (Country)

Результат:

Store   Country
A       USA, Japan
B       USA, China
C       USA, China, UK
D       UK, Australia
E       USA, Australia

Если вы можете перейти на SQL Server 2017, агрегирование строк можно выполнить с помощью STRING_AGG():

SELECT s.Store, t.Country
FROM Store s
CROSS APPLY (
   SELECT STRING_AGG(c.CountryName, N', ')
   FROM OPENJSON(s.Countries) WITH (CountryKey int '$') j
   LEFT JOIN Country c ON c.CountryKey = j.CountryKey
) t (Country)
...