如何将2个select语句组合成一个?

时间:2009-02-12 18:41:39

标签: sql select conditional

在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语句组合成一个很好的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)

8 个答案:

答案 0 :(得分:60)

这里有两个选择。第一个是有两个结果集,它们将根据WHERE子句中的条件设置'Test1'或'Test2',然后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 ...)

这可能是一个问题,因为您将在TABLE上有效地扫描/搜索两次。

另一个解决方案是从表中选择一次,并根据TABLE中的条件设置'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语句中复制过滤条件。

答案 1 :(得分:9)

如果他们来自同一张桌子,我认为UNION是您正在寻找的命令。

(如果您需要从不同表的列中选择值,则应该查看JOIN而不是......)

答案 2 :(得分: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示例,但没有按预期工作。

答案 3 :(得分:1)

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。

答案 4 :(得分:1)

The Union command is what you need.如果这不起作用,您可能需要改进您所处的环境。

答案 5 :(得分:1)

使用一个case进入select并使用在哪里关闭一个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')

答案 6 :(得分:1)

我认为这就是你要找的东西:

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

,效率更高。

答案 7 :(得分:0)

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

另一种方法!