我如何将2个select语句组合成一个?
当谈到SQL语法时,我是一个noob。
我有一个有很多行和列的表格:P让我们说看起来像这样:
AAA BBB CCC DDD ----------------------- Row1 | 1 ADX Row2 | 2 BCX Row3 | 3 CDZ
现在我想创build一个高级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语句),它会起作用吗? 我只想知道如何组合select,然后尝试将其应用于我的更高级的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语句的一个副本结合起来,并且'状态'字段将被改变为'DELETED'string。
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)
你有两个select。 首先是有两个结果集,它们将根据WHERE
子句中的条件设置“Test1”或“Test2”,然后将它们联合在一起:
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 ...)
这可能是一个问题,因为你将有效地扫描/查找表两次。
另一种解决scheme是从表中select一次,并根据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
语句中的过滤条件。
如果他们来自同一张桌子,我认为UNION
是你要找的命令。
(如果你需要从不同表格的列中select值,你应该看看JOIN
而不是…)
感谢您的input。 试了一下这里提到的东西,这两个是我上class的:
( 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)实际上是一个variables(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)
也许这会做的伎俩。 我不能从这里testing它,但我不确定你正在使用什么版本的SQL。
联盟命令是你所需要的。 如果这不起作用,您可能需要改进您所处的环境。
使用案例进入select和使用在哪里closures一个或
这样的事情,我没有testing,但它应该工作,我认为…
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
另一种方法来做到这一点!