涉及子查询的SQL Server查询 - 性能问题

时间:2017-04-07 06:31:29

标签: sql-server database performance subquery

我有三张桌子:

表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

2 个答案:

答案 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