SQL 服务器:JSON 可以格式化分组吗?
SQL Server : JSON formatting grouping possible?
我有一个 SQL 服务器 table 的形式:
192.168.1.1, 80 , tcp
192.168.1.1, 443, tcp
...
我正在将其导出到 json,如下所示:
SELECT
hostIp AS 'host.ip',
'ports' = (SELECT port AS 'port', protocol AS 'protocol'
FOR JSON PATH)
FROM
test
FOR JSON PATH
此查询结果:
[
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 80,
"protocol": "tcp"
}
]
},
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 443,
"protocol": "tcp"
}
]
},
....
但是我希望来自单个 IP 的所有数据都这样分组:
[
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 80,
"protocol": "tcp"
},
{
"port": 443,
"protocol": "tcp"
}
]
},
...
我发现似乎有聚合函数,但它们要么对我不起作用,要么对 Postgresql 不起作用,我的示例在 SQL Server.
知道如何让它工作吗?
唯一简单的方法是 self-join
SELECT
tOuter.hostIp AS [host.ip]
,ports = (
SELECT
tInner.port
,tInner.protocol
FROM test tInner
FOR JSON PATH
)
FROM test tOuter
GROUP BY
tOuter.hostIp
FOR JSON PATH;
显然self-join效率低下,但是SQL服务器不支持JSON_AGG
。你可以用 STRING_AGG
模拟它,不用 self-join
SELECT
t.hostIp AS [host.ip]
,ports = JSON_QUERY('[' + STRING_AGG(tInner.json, ',') + ']')
FROM test t
CROSS APPLY (
SELECT
t.port
,t.protocol
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) tInner(json)
GROUP BY
t.hostIp
FOR JSON PATH;
正如您想象的那样,随着涉及的嵌套级别越来越多,它会变得越来越复杂。
Note:
- Do not use
'
for quoting column names, only []
- There is no need to alias a column for JSON if it is already that name
我有一个 SQL 服务器 table 的形式:
192.168.1.1, 80 , tcp
192.168.1.1, 443, tcp
...
我正在将其导出到 json,如下所示:
SELECT
hostIp AS 'host.ip',
'ports' = (SELECT port AS 'port', protocol AS 'protocol'
FOR JSON PATH)
FROM
test
FOR JSON PATH
此查询结果:
[
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 80,
"protocol": "tcp"
}
]
},
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 443,
"protocol": "tcp"
}
]
},
....
但是我希望来自单个 IP 的所有数据都这样分组:
[
{
"host": {
"ip": "192.168.1.1"
},
"ports": [
{
"port": 80,
"protocol": "tcp"
},
{
"port": 443,
"protocol": "tcp"
}
]
},
...
我发现似乎有聚合函数,但它们要么对我不起作用,要么对 Postgresql 不起作用,我的示例在 SQL Server.
知道如何让它工作吗?
唯一简单的方法是 self-join
SELECT
tOuter.hostIp AS [host.ip]
,ports = (
SELECT
tInner.port
,tInner.protocol
FROM test tInner
FOR JSON PATH
)
FROM test tOuter
GROUP BY
tOuter.hostIp
FOR JSON PATH;
显然self-join效率低下,但是SQL服务器不支持JSON_AGG
。你可以用 STRING_AGG
模拟它,不用 self-join
SELECT
t.hostIp AS [host.ip]
,ports = JSON_QUERY('[' + STRING_AGG(tInner.json, ',') + ']')
FROM test t
CROSS APPLY (
SELECT
t.port
,t.protocol
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) tInner(json)
GROUP BY
t.hostIp
FOR JSON PATH;
正如您想象的那样,随着涉及的嵌套级别越来越多,它会变得越来越复杂。
Note:
- Do not use
'
for quoting column names, only[]
- There is no need to alias a column for JSON if it is already that name