2

我的数据看起来像:

客户

CustomerId  CustomerName CustomerEmail  
------------------------------------------
1           Ben          Ben@gmail.com
2           Robert       Robert@gmail.com
3           Paul         Paul@gmail.com

客户联系人

CustomerContactId  CustomerId  ContactName   ContactEmail
----------------------------------------------------------
99                 1           Lisa          Lisa@msn.com
98                 3           Jane          Jane@msn.com
97                 3           Wendy         Wendy@msn.com

这是我正在寻找的结果:

[
    {
        "CustomerId": 1,
        "Names": [ "Ben","Lisa" ],
        "Emails": [ "Ben@gmail.com","Lisa@msn.com" ]
    },
    {
        "CustomerId": 2,
        "Names": [ "Robert" ],
        "Emails": [ "Robert@gmail.com" ]
    },
    {
        "CustomerId": 3,
        "Names": [ "Paul","Jane","Wendy" ],
        "Emails": [ "Paul@gmail.com","Jane@msn.com","Wendy@msn.com" ]
    }
]

我尝试过的: 我很尴尬地说我还没有接近:

SELECT 
    Customers.CustomerId,
     STUFF( ISNULL(',' + Customers.CustomerName, '') + ISNULL(',' + CustomerContacts.ContactName, ''),1,1,'') as Names
FROM Customers
FULL JOIN CustomerContacts
ON Customers.CustomerId = CustomerContacts.CustomerId
GROUP BY Customers.CustomerId;
4

1 回答 1

3

不幸的是,SQL Server 在游戏中加入 JSON 的行列有点晚(仅在 2016 版本中开始内置支持),这意味着它对 JSON 的支持仍然不是很好(尽管它确实知道如何做到这一点很好)。 就个人而言,
我不知道有任何内置方法可以通过查询
(条款。{"Name":["Value1", "Value2"...]}
["Name":"Value1", "Name":"Value2"...]FOR JSON

但是,由于您使用的是 2017 和 Azure 版本,因此很容易自己生成这样string_agg的数组,使用(在早期版本中有点麻烦 - 使用for xml pathstuff聚合字符串)。

话虽这么说 - 这是我提出的解决方案:

首先,创建并填充示例表(在以后的问题中保存此步骤):

CREATE TABLE Customers (
    [CustomerId] int, 
    [CustomerName] varchar(6), 
    [CustomerEmail] varchar(16)
);

INSERT INTO Customers ([CustomerId], [CustomerName], [CustomerEmail]) VALUES
(1, 'Ben', 'Ben@gmail.com'),
(2, 'Robert', 'Robert@gmail.com'),
(3, 'Paul', 'Paul@gmail.com');

CREATE TABLE CustomerContacts (
    [CustomerContactId] int, 
    [CustomerId] int, 
    [ContactName] varchar(5), 
    [ContactEmail] varchar(13)
);

INSERT INTO CustomerContacts ([CustomerContactId], [CustomerId], [ContactName], [ContactEmail]) VALUES
(99, 1, 'Lisa', 'Lisa@msn.com'),
(98, 3, 'Jane', 'Jane@msn.com'),
(97, 3, 'Wendy', 'Wendy@msn.com');

然后,使用查询FOR JSON PATH来获取 json 输出。这里的技巧是通过将/与表中相关列的子查询的结果
连接起来来生成内部数组。 请注意这些列的包装。需要它们来防止 SQL Server 转义json 输出中的字符 - 通过告诉它内容是正确的 JSON。另外,请注意to 的用法- 您将获得所有客户,即使他们在表中没有相应的记录。CustomerNameCustomerEmailSTRING_AGGCustomerContacts
JSON_QUERY"
ISNULLLEFT JOINCustomerContacts

SELECT  C.CustomerId, 
        JSON_QUERY(
            '["' + C.CustomerName + ISNULL('","'+ 
            (
                SELECT STRING_AGG(CC.ContactName, '","') WITHIN GROUP (ORDER BY CustomerContactId)
                FROM CustomerContacts As CC
                WHERE CC.CustomerId = C.CustomerId
            ), '') + '"]'
        ) As Names,
        JSON_QUERY(
            '["' + C.CustomerEmail + ISNULL('","'+ 
            (
                SELECT STRING_AGG(CC.ContactEmail, '","') WITHIN GROUP (ORDER BY CustomerContactId)
                FROM CustomerContacts As CC
                WHERE CC.CustomerId = C.CustomerId
            ), '') + '"]'
        ) As Emails
FROM Customers AS C
FOR JSON PATH

结果:

[
    {
        "CustomerId": 1,
        "Names": ["Ben", "Lisa"],
        "Emails": ["Ben@gmail.com", "Lisa@msn.com"]
    }, {
        "CustomerId": 2,
        "Names": ["Robert"],
        "Emails": ["Robert@gmail.com"]
    }, {
        "CustomerId": 3,
        "Names": ["Paul", "Wendy", "Jane"],
        "Emails": ["Paul@gmail.com", "Wendy@msn.com", "Jane@msn.com"]
    }
]

你可以看到一个现场演示 (不幸的是,json 输出的缩进不是很好,但它仍然有效)DB<>Fiddle

于 2019-12-19T20:44:29.117 回答