1

Below is schema of the data stored in SQL Server 2016 Database

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

And in the Store table the information is saved as JSON

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

This design is working fine when I want to filter data, for example I'm able to use OPEN_JSON to filter the stores based on CountryKey

But after filter - the requirement is to show Country Name instead of Country Key as shown below -

Desired Output

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

My Question is can this be achieved with SQL Query or need to process data with server side language e.g C#. If yes syntax and references will help.

3
  • 3
    Personally, I would suggest fixing the design to a normalised approach. Not only do you need to split the data here, you then want to rebuild it into a comma separated list. Commented Mar 12, 2020 at 10:09
  • But the advantage of using JSON in SQL server 2016 will be gone. I need this tabular information only for report. Commented Mar 12, 2020 at 10:43
  • Storing relational data is not what you're meant to be using JSON data in SQL server for though. That should be in normalised tables. Commented Mar 12, 2020 at 10:45

1 Answer 1

2

One possible solution is to parse the country code with OPENJSON(), use appropriate join and aggregate the country names. For SQL Server 2016 you need to use FOR XML PATH for string aggregation:

Tables:

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]')

Statement:

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)

Result:

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

If you can upgrade to SQL Server 2017, string aggregation can be done using 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)
Sign up to request clarification or add additional context in comments.

1 Comment

Great this is exactly the same output, I was looking for

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.