Подтвердить что ты не робот

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)

В принципе, мне нужны две самые последние записи для двух конкретных типов данных.

Я хочу объединить эти два запроса вместе так:

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. И он не может иметь top 2 без order by.

Как я могу исправить эту ситуацию?

4b9b3361

Ответ 1

Вы должны иметь возможность псевдонизировать их и использовать в качестве подзапросов (часть причины, по которой ваша первая попытка была недействительной, состояла в том, что первый выбор состоял из двух столбцов (ID и ReceivedDate), но у вашей второй был только один (ID) - также Type является зарезервированным словом в 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

Ответ 2

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

Ответ 3

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

Ответ 4

Основная предпосылка вопроса и ответы неверны. Каждый элемент Select в объединении может иметь предложение where. Это ORDER BY в первом запросе, который дает ошибку.

Ответ 5

Ответ вводит в заблуждение, поскольку он пытается исправить проблему, которая не является проблемой. У вас на самом деле МОЖЕТ БЫТЬ КЛАССА WHERE в каждом сегменте UNION. У вас не может быть 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

Ответ 6

Создавать представления на двух первых "выбирает" и "объединяет" их.

Ответ 7

Обратите внимание, что каждый оператор SELECT в UNION должен иметь одинаковое количество столбцов. Столбцы также должны иметь похожие типы данных. Кроме того, столбцы в каждой инструкции SELECT должны быть в том же порядке. вы выбираете

t1.ID, t2.ReceivedDate   из таблицы t1

объединение

t2.ID   из таблицы t2

что неверно.

поэтому вам нужно написать

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 

поэтому он возвращает только разные значения по умолчанию из обеих таблиц.