Как объединить 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
заявление.
Спасибо за вход. Пробовал вещи, которые были упомянуты здесь, и это 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
другой способ сделать это!