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

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

Я использую noob, когда дело доходит до синтаксиса SQL.

У меня есть таблица с большим количеством строк и столбцов: P Предположим, что это выглядит так:

      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 в один оператор nice 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 ...)




Мой REAL 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 с добавленным AND в конце, а поле "Status" будет изменено с помощью строки типа "DELETED".

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)
4b9b3361

Ответ 1

У вас есть два варианта. Первое состоит в том, чтобы иметь два набора результатов, которые будут устанавливать "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

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

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

Ответ 3

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

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

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

Ответ 4

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 вы работаете.

Ответ 6

использовать случай в select и использовать в том, где close a OR

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

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

Ответ 7

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

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

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

Ответ 8

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

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