web-dev-qa-db-ja.com

SQL Server:両方にWHERE句がある2つのクエリでUNIONを使用する方法は?

指定:

フィルタリングが必要な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

個別に、これらは私が探しているIDsを返します:(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

問題:

問題は、最初のselectunionedである場合、order by句を含むことができないため、このクエリが無効であることです。そして、top 2がなければorder byを持つことはできません。

この状況を修正するにはどうすればよいですか?

26
aarona

それらをエイリアスし、サブクエリとして使用できるはずです(最初の努力が無効だった理由の一部は、最初の選択に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
41
Ken White
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
9
amit_g
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
5
Mikael Eriksson

質問と答えの基本的な前提は間違っています。ユニオンのすべてのSelectには、where句を含めることができます。エラーを発生させるのは、最初のクエリのORDER BYです。

4
Paul Nielsen

答えは、問題ではない問題を修正しようとするため、誤解を招きます。実際には、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
3
user2967439

最初の2つの「選択」ビューと「結合」ビューを作成します。

0
Pavel Nefyodov

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 

そのため、デフォルトでは両方のテーブルから個別の値のみを返します。

0
Pradeep atkari