我有三张桌子:
表1:| dbo.pc_a21a22 |
batchNbr Other columns...
-------- ----------------
12345
12346
12347
表2:| dbo.outcome |
passageId record
---------- ---------
00003 200
00003 9
00004 7
表3:| dbo.passage |
passageId passageTime batchNbr
---------- ------------- ---------
00001 2015.01.01 12345
00002 2016.01.01 12345
00003 2017.01.01 12345
00004 2018.01.01 12346
我想做什么:对于表1中的每个batchNbr,首先获取其最新的passageTime和表3中的相应的passageID。使用该passageID,获取表2中的相关行并确定这些行中的任何行是否包含记录200 。每次通过表2中最多有2条记录
最有效的方法是什么?
我已经创建了一个可行的查询,但它非常慢,因此不适合具有数百万行的表。有关如何更改查询或以其他方式执行操作的任何建议?改变表结构不是一种选择,我只对数据库有读权限。
我目前的解决方案(慢):
SELECT TOP 50000
a.batchNbr,
CAST ( CASE WHEN 200 in (SELECT TOP 2 record FROM dbo.outcome where passageId in (
SELECT SubqueryResults.passageId From (SELECT Top 1 passageId FROM dbo.passage pass WHERE pass.batchNbr = a.batchNbr ORDER BY passageTime Desc) SubqueryResults
)
) then 1 else 0 end as bit) as KGT_IO_END
FROM dbo.pc_a21a22 a
所需的输出是:
batchNbr 200present
--------- ----------
12345 1
12346 0
答案 0 :(得分:3)
我建议你使用表连接而不是子查询。
Select * from Histroy where History.UsernameColumnname='Admin'
and History.PasswordColumnname='12345'
编辑:
您可以将其用作参考Join vs. sub-query
答案 1 :(得分:1)
试试这个
SELECT TOP 50000 a.*, (CASE WHEN b.record = 200 THEN 1 ELSE 0 END) AS
KGT_IO_END
FROM dbo.Test1 AS a
LEFT OUTER JOIN
(SELECT record, p.batchNbr
FROM dbo.Test2 AS o
LEFT OUTER JOIN (SELECT MAX(passageId) AS passageId, batchNbr FROM
dbo.Test3 GROUP BY batchNbr) AS p ON o.passageId = p.passageId
) AS b ON a.batchNbr = b.batchNbr;
MAX
子查询是通过passageId
获取最新的batchNbr
。
但是,您的示例无法获得记录200,因为200的记录的passageId
是00001,而passageId
12345的最新batchNbr
是00003。
我使用LEFT OUTER JOIN
,因为Table2中的passageId
不再与Table3中的任何最新passageId
匹配。生成的子查询将没有join
到Table1的记录。因此,INNER JOIN
不会显示示例数据中的任何记录。
示例数据的输出:
batchNbr KGT_IO_END
12345 0
12346 0
12347 0
如果我们将记录200的passageId
更改为00003(最新的12345),则输出
batchNbr KGT_IO_END
12345 1
12346 0
12347 0