【问题标题】:SQL Server JSON array foreign key values using join使用连接的 SQL Server JSON 数组外键值
【发布时间】:2020-03-12 10:07:43
【问题描述】:

以下是存储在 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 而不是 Country Key,如下所示 -

期望的输出

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

我的问题是可以使用SQL Query 来实现,还是需要使用服务器端语言处理数据,例如C#。 如果是,语法和引用会有所帮助。

【问题讨论】:

  • 就个人而言,我建议将设计修复为标准化方法。您不仅需要在此处拆分数据,然后还希望将其重建为逗号分隔的列表。
  • 但是在 SQL server 2016 中使用 JSON 的优势将会消失。我只需要这个表格信息来报告。
  • 存储关系数据并不是您在 SQL Server 中使用 JSON 数据的目的。这应该在规范化表中。

标签: sql json sql-server foreign-keys sql-server-2016


【解决方案1】:

一种可能的解决方案是使用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)

【讨论】:

  • 太好了,这是完全相同的输出,我一直在寻找
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多