29 Stimmen

SQL Server: Wie kann man UNION mit zwei Abfragen verwenden, die beide eine WHERE-Klausel haben?

Gegeben:

Zwei Abfragen, die gefiltert werden müssen:

select top 2 t1.ID, t1.ReceivedDate
  from Table t1
 where t1.Type = 'TYPE_1'
 order by t1.ReceivedDate desc

Und:

select top 2 t2.ID
  from Table t2
 where t2.Type = 'TYPE_2'
 order by t2.ReceivedDate desc

Getrennt davon geben diese die ID s, die ich suche: (13, 11 und 12, 6)

Im Grunde möchte ich die beiden jüngsten Datensätze für zwei bestimmte Datentypen.

Ich möchte diese beiden Abfragen folgendermaßen zusammenführen:

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

Problem:

Das Problem ist, dass diese Abfrage ungültig ist, weil die erste select kann nicht über eine order by Klausel, wenn es sich um unioned . Und es kann nicht haben top 2 ohne dass die order by .

Wie kann ich diese Situation beheben?

41voto

Ken White Punkte 120217

Sie sollten in der Lage sein, sie zu aliasieren und als Unterabfragen zu verwenden (ein Teil des Grundes, warum Ihr erster Versuch ungültig war, war, weil die erste Auswahl zwei Spalten (ID und ReceivedDate) hatte, aber Ihre zweite nur eine (ID) - auch, Typ ist ein reserviertes Wort in SQL Server, und kann nicht verwendet werden, wie Sie es als einen Spaltennamen hatte):

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

10voto

amit_g Punkte 29895
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

oder mit 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

6voto

Mikael Eriksson Punkte 132244
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

4voto

Paul Nielsen Punkte 41

Die Grundannahme der Frage und die Antworten sind falsch. Jedes Select in einer Union kann eine Where-Klausel haben. Es ist das ORDER BY in der ersten Abfrage, das Ihnen den Fehler beschert.

3voto

user2967439 Punkte 57

Die Antwort ist irreführend, weil sie versucht, ein Problem zu lösen, das keines ist. Sie KÖNNEN tatsächlich eine WHERE-KLAUSEL in jedem Segment einer UNION haben. Sie können nur im letzten Segment eine ORDER BY haben. Daher sollte dies funktionieren...

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X