SQL Server array_agg(主 - 详细信息)

时间:2016-12-14 08:23:01

标签: sql-server tsql

如何将此PostgreSQL代码转换为SQL Server?

select 
    countries.title, 
    (select array_to_json(array_agg(row_to_json(t))) 
     from postcodes t 
     where t.country_id = countries.id) as codes 
from countries

我最初的问题是我需要选择完整的主表并且每行都包含所有细节。

国家

id    title
1     SLO
2     AUT

邮政编码

id  country_id  code    title
1   1           1000    Lj
2   1           2000    Mb
3   2           22180   Vi
4   2           22484   De

期望的结果:

1  SLO  1000;Lj|2000;MB
2  AUT  22180;Vi|22484;De

1  SLO  1000  Lj
1  SLO  2000  Mb
2  AUT  22180 Vi
2  AUT  22484 De

最好的解决方案是使用FOR JSON,但不幸的是我需要支持2008年或至少2012年。

使用左连接时,所有主数据都会被重复以进行详细计数,但我不想这样做。更糟糕的是,选择所有国家/地区,然后为{for循环中的每个国家/地区post_codes调用select。

3 个答案:

答案 0 :(得分:4)

select countries.title, 
       STUFF((select '|' + t.code + ';' + t.title
                from postcodes t 
                where t.country_id = countries.id
                FOR XML PATH('')
              ),1,1,'') as codes 
     from countries

- CAST t.code to VARCHAR,如果它是Number

答案 1 :(得分:0)

试试这个:

Select Main.COUNTRY_ID,c.title,Left(Main.POSTCODES,Len(Main.POSTCODES)-1) As "POSTCODES"
From
    (
        Select distinct ST2.COUNTRY_ID, 
            (
                Select ST1.CODE+';'+ST1.TITLE + '|' AS [text()]
                From dbo.POSTCODES ST1
                Where ST1.COUNTRY_ID = ST2.COUNTRY_ID
                ORDER BY ST1.COUNTRY_ID
                For XML PATH ('')
            ) [POSTCODES]
        From dbo.POSTCODES ST2
    ) [Main]

    inner join countries c on c.id=main.country_id

答案 2 :(得分:0)

使用XML PATH进行连接可能会增加代码的复杂性。最好实现CLR aggregation function。然后,您可以执行以下操作:

SELECT C.[id]
      ,C.[title]
      ,REPLACE([dbo].[Concatenate] (P.[code] + ';' + P.[title]), ',', '|')
FROM @Countries C
INNER JOIN @PostCodes P
    ON C.[id] = p.[country_id]
GROUP BY C.[id]
        ,C.[title];

您可以创建自己的连接聚合版本 - 您可以指定分隔符,顺序等。如果您愿意,我可以向您展示示例。

DECLARE @Countries TABLE
(
    [id] TINYINT
   ,[title] VARCHAR(12)
);

INSERT INTO @Countries ([id], [title])
VALUES (1, 'SLO')
      ,(2, 'AUT');

DECLARE @PostCodes TABLE
(
    [id] TINYINT
   ,[country_id] TINYINT
   ,[code] VARCHAR(12)
   ,[title] VARCHAR(12)
);

INSERT INTO @PostCodes ([id], [country_id], [code], [title])
VALUES (1, 1, 1000, 'Lj')
      ,(2, 1, 2000, 'Mb')
      ,(3, 2, 22180, 'Vi')
      ,(4, 2, 22484, 'De');

SELECT C.[id]
      ,C.[title]
      ,REPLACE([dbo].[Concatenate] (P.[code] + ';' + P.[title]), ',', '|')
FROM @Countries C
INNER JOIN @PostCodes P
    ON C.[id] = p.[country_id]
GROUP BY C.[id]
        ,C.[title];

enter image description here