指定:
フィルタリングが必要な2つのクエリ:
select top 2 t1.ID, t1.ReceivedDate
from Table t1
where t1.Type = 'TYPE_1'
order by t1.ReceivedDate desc
そして:
select top 2 t2.ID
from Table t2
where t2.Type = 'TYPE_2'
order by t2.ReceivedDate desc
個別に、これらは私が探しているID
sを返します:(13、11 and 12、6)
基本的に、2つの特定の種類のデータの2つの最新のレコードが必要です。
これらの2つのクエリを次のように結合します。
select top 2 t1.ID, t2.ReceivedDate
from Table t1
where t1.Type = 'TYPE_1'
order by ReceivedDate desc
union
select top 2 t2.ID
from Table t2
where t2.Type = 'TYPE_2'
order by ReceivedDate desc
問題:
問題は、最初のselect
がunioned
である場合、order by
句を含むことができないため、このクエリが無効であることです。そして、top 2
がなければorder by
を持つことはできません。
この状況を修正するにはどうすればよいですか?
それらをエイリアスし、サブクエリとして使用できるはずです(最初の努力が無効だった理由の一部は、最初の選択に2つの列(IDとReceivedDate)があったが、2番目の列には1つ(ID)しかなかったためです-また、Typeは予約済みですSQL ServerのWordで、列名として使用したとおりに使用することはできません):
declare @Tbl1 table(ID int, ReceivedDate datetime, ItemType Varchar(10))
declare @Tbl2 table(ID int, ReceivedDate datetime, ItemType Varchar(10))
insert into @Tbl1 values(1, '20010101', 'Type_1')
insert into @Tbl1 values(2, '20010102', 'Type_1')
insert into @Tbl1 values(3, '20010103', 'Type_3')
insert into @Tbl2 values(10, '20010101', 'Type_2')
insert into @Tbl2 values(20, '20010102', 'Type_3')
insert into @Tbl2 values(30, '20010103', 'Type_2')
SELECT a.ID, a.ReceivedDate FROM
(select top 2 t1.ID, t1.ReceivedDate
from @tbl1 t1
where t1.ItemType = 'TYPE_1'
order by ReceivedDate desc
) a
union
SELECT b.ID, b.ReceivedDate FROM
(select top 2 t2.ID, t2.ReceivedDate
from @tbl2 t2
where t2.ItemType = 'TYPE_2'
order by t2.ReceivedDate desc
) b
select * from
(
select top 2 t1.ID, t1.ReceivedDate
from Table t1
where t1.Type = 'TYPE_1'
order by t1.ReceivedDate de
) t1
union
select * from
(
select top 2 t2.ID
from Table t2
where t2.Type = 'TYPE_2'
order by t2.ReceivedDate desc
) t2
またはCTEを使用(SQL Server 2005+)
;with One as
(
select top 2 t1.ID, t1.ReceivedDate
from Table t1
where t1.Type = 'TYPE_1'
order by t1.ReceivedDate de
)
,Two as
(
select top 2 t2.ID
from Table t2
where t2.Type = 'TYPE_2'
order by t2.ReceivedDate desc
)
select * from One
union
select * from Two
declare @T1 table(ID int, ReceivedDate datetime, [type] varchar(10))
declare @T2 table(ID int, ReceivedDate datetime, [type] varchar(10))
insert into @T1 values(1, '20010101', '1')
insert into @T1 values(2, '20010102', '1')
insert into @T1 values(3, '20010103', '1')
insert into @T2 values(10, '20010101', '2')
insert into @T2 values(20, '20010102', '2')
insert into @T2 values(30, '20010103', '2')
;with cte1 as
(
select *,
row_number() over(order by ReceivedDate desc) as rn
from @T1
where [type] = '1'
),
cte2 as
(
select *,
row_number() over(order by ReceivedDate desc) as rn
from @T2
where [type] = '2'
)
select *
from cte1
where rn <= 2
union all
select *
from cte2
where rn <= 2
質問と答えの基本的な前提は間違っています。ユニオンのすべてのSelectには、where句を含めることができます。エラーを発生させるのは、最初のクエリのORDER BYです。
答えは、問題ではない問題を修正しようとするため、誤解を招きます。実際には、UNIONの各セグメントにWHERE句を含めることができます。最後のセグメントを除き、ORDER BYを持つことはできません。したがって、これは動作するはずです...
select top 2 t1.ID, t1.ReceivedDate
from Table t1
where t1.Type = 'TYPE_1'
-----remove this-- order by ReceivedDate desc
union
select top 2 t2.ID, t2.ReceivedDate --- add second column
from Table t2
where t2.Type = 'TYPE_2'
order by ReceivedDate desc
最初の2つの「選択」ビューと「結合」ビューを作成します。
UNION内の各SELECTステートメントには同じ数の列が必要であることに注意してください。列にも同様のデータ型が必要です。また、各SELECTステートメントの列は同じ順序でなければなりません。あなたが選択しています
テーブルt1からのt1.ID、t2.ReceivedDate
連合
テーブルt2のt2.ID
間違っています。
だからあなたは書く必要があります
テーブルt1ユニオンからのt1.ID、t1.ReceivedDate t2.ID、テーブルt1からのt2.ReceivedDate
ここでサブクエリを使用できます
SELECT tbl1.ID, tbl1.ReceivedDate FROM
(select top 2 t1.ID, t1.ReceivedDate
from tbl1 t1
where t1.ItemType = 'TYPE_1'
order by ReceivedDate desc
) tbl1
union
SELECT tbl2.ID, tbl2.ReceivedDate FROM
(select top 2 t2.ID, t2.ReceivedDate
from tbl2 t2
where t2.ItemType = 'TYPE_2'
order by t2.ReceivedDate desc
) tbl2
そのため、デフォルトでは両方のテーブルから個別の値のみを返します。