SQL Server中如何将JSON数组外键转为逗号分隔的产品名称列表?
问题描述
假设SQL Server数据库中有以下两张表:
products表
| id | product_name |
|---|---|
| 1 | "Apple" |
| 2 | "Banana" |
| 3 | "Pear" |
| 4 | "Peach" |
users表
| id | user_name | likedProductsIds(存储products表行ID的JSON数组) |
|---|---|---|
| 1 | "Joe" | "[1,2,3,4]" |
| 2 | "Jose" | "[3,4]" |
| 3 | "Kim" | NULL |
| 4 | "Kelly" | "[4]" |
需要创建名为report的SQL视图,将users表中的likedProductsIds转换为对应的产品名称逗号分隔列表,预期结果如下:
report视图预期结果
| id | name | likedProductNames |
|---|---|---|
| 1 | "Joe" | "Apple, Banana, Pear, Peach" |
| 2 | "Jose" | "Pear, Peach" |
| 3 | "Kim" | NULL |
| 4 | "Kelly" | "Peach" |
作为SQL新手,已知需要用OPENJSON反序列化JSON数组、STRING_AGG聚合产品名称,但不知道如何结合两者完成查询。
解决方案
可以通过子查询+聚合函数的方式,将OPENJSON解析出的产品ID与products表关联,再用STRING_AGG拼接名称,最后和users表关联得到结果,这种写法更简洁直观。
创建视图的SQL语句
CREATE VIEW report AS SELECT u.id, u.user_name AS name, ( SELECT STRING_AGG(p.product_name, ', ') FROM OPENJSON(u.likedProductsIds) WITH (productId INT '$') AS j JOIN products p ON j.productId = p.id ) AS likedProductNames FROM users u;
语句说明
- 解析JSON数组:
OPENJSON(u.likedProductsIds) WITH (productId INT '$')会把JSON数组中的每个ID解析成单独一行,列名为productId并转为INT类型。 - 关联产品表:将解析出的
productId与products表的id匹配,获取对应的产品名称。 - 聚合拼接名称:
STRING_AGG函数把同一个用户的所有产品名称用,拼接成一个字符串。 - 自动处理NULL:如果
likedProductsIds为NULL,子查询会直接返回NULL,完全符合预期结果。
如果偏好CTE(公用表表达式)的写法,逻辑一致,只是需要额外用UNION ALL补充无喜欢产品的用户数据:
CREATE VIEW report AS WITH UserLikedProducts AS ( SELECT u.id, u.user_name, p.product_name FROM users u CROSS APPLY OPENJSON(u.likedProductsIds) WITH (productId INT '$') j JOIN products p ON j.productId = p.id ) SELECT id, user_name AS name, STRING_AGG(product_name, ', ') AS likedProductNames FROM UserLikedProducts GROUP BY id, user_name UNION ALL SELECT id, user_name AS name, NULL AS likedProductNames FROM users u WHERE u.likedProductsIds IS NULL;
内容的提问来源于stack exchange,提问作者WillD
相关产品推荐
相关产品推荐

