Как объединить 2 оператора select в один?

Я noob, когда дело доходит до синтаксиса SQL.

у меня есть таблица с большим количеством строк и столбцов, конечно :Р Скажем, это выглядит так:

      AAA BBB CCC DDD
-----------------------
Row1 | 1   A   D   X
Row2 | 2   B   C   X
Row3 | 3   C   D   Z

теперь я хочу создать расширенный оператор select, который дает мне это комбинированное (псевдо SQLish здесь):

select 'Test1', * from TABLE Where CCC='D' AND DDD='X'
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X'

выход такой:

Test1, 1, A, D, X
Test2, 2, B, C, X

как бы я объединил эти два оператора select в один хороший оператор select?

будет ли это работать, если я усложнил SQL как показано ниже (потому что мой собственный оператор SQL содержит оператор exists)? Я просто хочу знать, как я могу объединить выбор, а затем попытаться применить его к моему несколько более продвинутому SQL.

select 'Test1', * from TABLE Where CCC='D' AND DDD='X' AND exists(select ...)
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X' AND exists(select ...)




Мой настоящий SQL-оператор таков:

select Status, * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'

что дает мне результат. Но я хочу объединить его с копией этого оператора select с добавленным и в конце, и поле "Статус" будет изменено строкой, такой как "Исключено".

select 'DELETED', * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)

8 ответов


у вас есть два варианта здесь. Первый должен иметь два результирующих набора, которые будут устанавливать "Test1" или "Test2" на основе условия в WHERE предложение, а затем UNION их вместе:

select 
    'Test1', * 
from 
    TABLE 
Where 
    CCC='D' AND DDD='X' AND exists(select ...)
UNION
select 
    'Test2', * 
from 
    TABLE
Where
    CCC<>'D' AND DDD='X' AND exists(select ...)

это может быть проблемой, потому что вы собираетесь эффективно сканировать/искать на столе дважды.

другим решением было бы выбрать из таблицы один раз и установить "Test1" или "Test2" на основе условий в таблице:

select 
    case 
        when CCC='D' AND DDD='X' AND exists(select ...) then 'Test1'
        when CCC<>'D' AND DDD='X' AND exists(select ...) then 'Test2'
    end,
    * 
from 
    TABLE 
Where 
    (CCC='D' AND DDD='X' AND exists(select ...)) or
    (CCC<>'D' AND DDD='X' AND exists(select ...))

подвох здесь в том, что вы придется дублировать условия фильтра в CASE заявления и WHERE заявление.


если они из одной таблицы, я думаю UNION - это команда, которую вы ищете.

(Если вам когда-нибудь понадобится выбрать значения из столбцов разных таблиц, вы должны посмотреть на JOIN...)


Спасибо за вход. Пробовал вещи, которые были упомянуты здесь, и это 2, которые я получил на работу:

(
select 'OK', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND (BoolField05=1)
)
UNION
(
select 'DEL', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)
)

и

select 
    case
        when
            (BoolField05=1)
    then 'OK'
    else 'DEL'
        end,
        *
from WorkItems t1
Where
            exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
            AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
            AND TimeStamp>'2009-02-12 18:00:00'

что было бы наиболее эффективным из них (edit: второй, поскольку он сканирует таблицу только один раз),и можно ли сделать его еще более эффективным!--8-->? (BoolField=1) на самом деле является переменной (Dyn sql), которая может содержать любой оператор where в таблице.

Я работаю на MS SQL 2005. Пробовал Quassnoi примеры, но не работают, как ожидалось.


select Status, * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'

UNION

select 'DELETED', * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)

возможно, это поможет. Я не могу проверить это отсюда, и я не уверен, с какой версией SQL вы работаете.


команда Union-это то, что вам нужно. Если это не сработает, вам может понадобиться, чтобы уточнить, в какой среде вы находитесь.


используйте регистр в select и используйте в where close a или

что-то вроде этого, я не проверял, но должно работать, я думаю...

select case when CCC='D' then 'test1' else 'test2' end, *
from table
where (CCC='D' AND DDD='X') or (CCC<>'D' AND DDD='X')

Я думаю, что это то, что вы ищете:

SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*
FROM WorkItems t1
WHERE (TextField01, TimeStamp) IN(
  SELECT TextField01, MAX(TimeStamp)
  FROM WorkItems t2
  GROUP BY t2.TextField01
  )
AND TimeStamp > '2009-02-12 18:00:00'

Если вы находитесь в Oracle или в MS SQL 2005 и выше, то вы можете сделать:

SELECT *
FROM (
  SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*,
     ROW_NUMBER() OVER (PARTITION BY TextField01 ORDER BY TimeStamp DESC) AS rn
  FROM WorkItems t1
) to
WHERE rn = 1

, это более эффективно.


select t1.* from 
(select * from TABLE Where CCC='D' AND DDD='X') as t1,
(select * from TABLE Where CCC<>'D' AND DDD='X') as t2

другой способ сделать это!