トップ回答者
このようなクエリ組めますか?

質問
回答
-
他にもやり方があると思いますが、おそらく一番わかりやすいのは以下のSQLです。
select [ID-A], 名前, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 1 ) 購入品1, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 2 ) 購入品2, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 3 ) 購入品3 from dbo.テーブルA a order by [ID-A]
#購入品がnullになるのが嫌であれば、isnull関数を使って下さい。
#前提条件がわかりませんが、上のSQLでは同じ人が同じ商品を複数買うと破綻するんじゃないかと思います。もう少し詳しい条件を提示されると、それによってSQLが変わります。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
-
-
例えば、
ID-B ID-A 購入番号 購入品
1 1 1 もも
2 1 2 みかん
3 1 3 みかん
4 1 4 なし
だった場合、上記の私のSQLでは、
ID-A 名前 購入品1 購入品2 購入品3
1 伊藤 もも みかん みかんになります。
これを、ID-A 名前 購入品1 購入品2 購入品3
1 伊藤 もも みかん なしにしたいのであれば、
select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A]
を、以下のように変える必要があります。
select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from (select 購入品, min(購入番号) 購入番号 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] group by 購入品 ) t
以上のSQLでサブクエリを多用していますが、サブクエリは今回の件に関わらず重要なテクニックです。ぜひ、発想の一つに加えて下さい。
なお、今回の件に関しては、佐祐理さんが書かれているようにPIVOTを使うのがお勧めですが、条件によっては動的にSQLを組み立てる必要があります。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
-
とりあえず、わかっている範囲内の条件であれば、PIVOTのSQLを動的に作成する必要はなく、勝手に佐祐理さんのSQLを修正させていただければ、以下のようになりますね。
SELECT a.[ID-A], [名前], [1] AS 購入品1, [2] AS 購入品2, [3] AS 購入品3 FROM (SELECT [ID-A], num, [購入品] FROM (select [ID-A], 購入品, ROW_NUMBER() OVER(PARTITION BY [ID-A] ORDER BY min(購入番号)) num from dbo.テーブルB b group by [ID-A], 購入品) t ) AS b1 PIVOT ( MIN([購入品]) FOR num IN ([1], [2], [3]) ) AS b2 INNER JOIN [テーブルA] AS a ON a.[ID-A] = b2.[ID-A];
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 回答としてマーク HIRO_KU 2020年8月12日 6:11
すべての返信
-
他にもやり方があると思いますが、おそらく一番わかりやすいのは以下のSQLです。
select [ID-A], 名前, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 1 ) 購入品1, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 2 ) 購入品2, (select 購入品 from ( select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] ) tbl where 順位 = 3 ) 購入品3 from dbo.テーブルA a order by [ID-A]
#購入品がnullになるのが嫌であれば、isnull関数を使って下さい。
#前提条件がわかりませんが、上のSQLでは同じ人が同じ商品を複数買うと破綻するんじゃないかと思います。もう少し詳しい条件を提示されると、それによってSQLが変わります。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
-
-
例えば、
ID-B ID-A 購入番号 購入品
1 1 1 もも
2 1 2 みかん
3 1 3 みかん
4 1 4 なし
だった場合、上記の私のSQLでは、
ID-A 名前 購入品1 購入品2 購入品3
1 伊藤 もも みかん みかんになります。
これを、ID-A 名前 購入品1 購入品2 購入品3
1 伊藤 もも みかん なしにしたいのであれば、
select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from dbo.テーブルB b where b.[ID-A] = a.[ID-A]
を、以下のように変える必要があります。
select 購入品, DENSE_RANK() OVER(ORDER BY 購入番号) 順位 from (select 購入品, min(購入番号) 購入番号 from dbo.テーブルB b where b.[ID-A] = a.[ID-A] group by 購入品 ) t
以上のSQLでサブクエリを多用していますが、サブクエリは今回の件に関わらず重要なテクニックです。ぜひ、発想の一つに加えて下さい。
なお、今回の件に関しては、佐祐理さんが書かれているようにPIVOTを使うのがお勧めですが、条件によっては動的にSQLを組み立てる必要があります。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
-
とりあえず、わかっている範囲内の条件であれば、PIVOTのSQLを動的に作成する必要はなく、勝手に佐祐理さんのSQLを修正させていただければ、以下のようになりますね。
SELECT a.[ID-A], [名前], [1] AS 購入品1, [2] AS 購入品2, [3] AS 購入品3 FROM (SELECT [ID-A], num, [購入品] FROM (select [ID-A], 購入品, ROW_NUMBER() OVER(PARTITION BY [ID-A] ORDER BY min(購入番号)) num from dbo.テーブルB b group by [ID-A], 購入品) t ) AS b1 PIVOT ( MIN([購入品]) FOR num IN ([1], [2], [3]) ) AS b2 INNER JOIN [テーブルA] AS a ON a.[ID-A] = b2.[ID-A];
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 回答としてマーク HIRO_KU 2020年8月12日 6:11