2016-12-14 4 views
0

このPostgreSQLコードをSQL Serverに変換するにはどうすればよいですか?SQL Server array_agg(master - detail)

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を選択することができます。

+0

SQL Server 2008のは、サポートされなくなりました。 2012年はサポートされている最初のバージョンですが、Columnstoreインデックス、圧縮、インメモリテーブル、SQL Server ExpressおよびLocalDB(SP1を使用)でのパーティショニングでも2016が当然選択されます。 T-SQLのコードJSON生成よりも安価かもしれません –

+1

私は知っていますが、500人のクライアントに新しいSQLを購入すべきだと説得するのは不可能です。彼らは私たちの製品が2005年と一緒に働くことを望んでいます。 :) – Makla

+1

データは無料のSQL Server Expressバージョンに収まるものの、とにかく、このような変換は、*クライアント*上ではるかに簡単で安全です。データベースの文字列操作は高価です。また、エスケープする必要があるデータがある場合はどうしますか? –

答えて

3
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 

- VARCHARへのCASTのt.codeそれは数

0

だ場合は、これを試してください:連結用XML PATHを使用して

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 
0

はあなたのコードの複雑さを増すことができます。 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]; 

あなたはCONCATENATE集合体の独自のバージョンを作成することができます - あなたは、区切り文字、順序などを指定することができますしたい場合、私はあなたの例を示すことができます。

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

関連する問題