在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)
答案 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)
答案 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
另一种方法!