2011-03-24 30 views
24

考虑:SQL Server:如何使用UNION和两个查询都有WHERE子句?

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了,我就是在寻找:(13,11和12,6)

基本上,我想要两个特定的最近两个记录数据的pes。

我想联盟这两个查询等一起这样:

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不能有order by条款,如果它是正在unioned。如果没有order by,它不能有top 2

我该如何解决这种情况?

+2

我想你的意思是,你有'顺序''不''哪里'的麻烦。 – 2011-03-24 23:39:19

回答

37

你应该能够别名他们和子查询使用你的第一个努力是无效的原因(部分是因为第一个选择有两列(ID和ReceivedDate),但你只有一秒钟(ID) - 此外,类型是SQL Server中的保留字,不能用作您把它作为一个列名):

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 
+3

感谢兄弟。这正是我需要的! – DJTripleThreat 2011-03-24 23:43:33

+0

@DJTripleThreat:我在编辑之前接受了。 :) – 2011-03-24 23:46:13

0

创建两个第一个“选择”和“联合”他们的意见。

+2

-1仅仅为了选择和合并而创建两个视图似乎是错误的。 – 2011-03-24 23:37:19

+0

+1,因为这个答案在技术上是正确的,但它不是最好的解决方案。 – DJTripleThreat 2011-03-24 23:45:23

+0

@Ken White你真的认为这是一个好主意,只是因为它们不是最好的解决方案才能投票回答答案吗?技术上正确的解决方案在30秒内完成,无需涉及任何代码。 @DJTripleThreat:谢谢你的专业态度。 – 2011-03-25 09:24:37

5
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 
+1

+1 @Mikael。这也是很好的例子! – DJTripleThreat 2011-03-24 23:44:35

8
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服务器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 
+1

为我工作就像一个魅力! – 2013-07-11 16:16:02

4

问题和答案的基本前提是错误的。在联合中的每个选择都可以有一个where子句。这是ORDER BY在第一个查询中给出的错误。

+0

所以我的评论= 15个字符,但这是答案。 – 2014-03-07 17:04:00

0

请注意,UNION中的每个SELECT语句必须具有相同的列数。这些列也必须具有相似的数据类型。另外,每个SELECT语句中的列必须以相同的顺序排列。 您选择

t1.ID,t2.ReceivedDate 从表T1

工会

从表T2

t2.ID

这是不正确。

,所以你必须写

t1.ID,t1.ReceivedDate从表T1 工会 t2.ID,t2.ReceivedDate从表T1

,你可以在这里使用子查询

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 

因此,它只会从这两个表中默认返回不同的值。

2

答案是误导性的,因为它试图解决一个不是问题的问题。你实际上可以在UNION的每个段中都有一个WHERE CLAUSE。除最后一段以外,您不能拥有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 
+0

第一个查询中的“TOP 2”需要第一个“ORDER BY” – OGHaza 2016-09-16 01:53:42