高效的SQL查询设计

时间:2011-08-22 22:55:29

标签: sql database database-design

通常认为进行此类查询的最有效方法是什么?

我们有一个包含10年实验室数据的数据库,我们希望为各种测试选择性能数据。例如,此查询将选择进行测试所花费的小时数并计算平均周转时间,并允许我们绘制每天平均TAT的迷你图。

假设我们有100个测试名称,在性能方面是否可接受迭代循环中的测试名称并在每个循环中关闭此查询一次?还是有更有效的方式?

SELECT 
  Date_Authorised_Index.Date_Authorised
  , Result_Set.Date_Booked_In
  , avg(DATEDIFF('hh',Result_Set.Date_Time_Booked_In,Result_Set.Date_Time_Authorised)) as HrsIn
  , count(Date_Authorised_Index.Date_Authorised) as numbers
  , Date_Authorised_Index.Registration_Number
  , Date_Authorised_Index.Request_Row_ID
  , Date_Authorised_Index.Specimen_Number
  , Result_Set.Authorised_By
  , Result_Set.Namespace
  , Result_Set.Set_Code
  , Result_Set.Date_Time_Authorised
  , Request.Date_Time_Received
  , Request.Location 
FROM 
  Date_Authorised_Index Date_Authorised_Index
  , Result_Set Result_Set
  , Request 
WHERE 
  Date_Authorised_Index.Date_Authorised = Result_Set.Date_Authorised 
  AND Date_Authorised_Index.Request_Row_ID = Request.Request_Row_ID
  AND Date_Authorised_Index.Request_Row_ID = Result_Set.Request_Row_ID 
  AND (Date_Authorised_Index.Discipline='C') AND Result_Set.Set_Code=? 
GROUP BY 
  Result_Set.Date_Booked_In

1 个答案:

答案 0 :(得分:0)

对于初学者,我会重写此查询,因此它使用显式连接语法 即使MySQL没有强制你重新使用group by子句中的每个非聚合列,这并不意味着这是一件好事。
除非Result_Set.Date_Booked_In唯一标识一行,否则您将从多行中选择随机值。

SELECT 
  dai.Date_Authorised
  , rs.Date_Booked_In
  , avg(DATEDIFF('hh',rs.Date_Time_Booked_In,rs.Date_Time_Authorised)) as HrsIn
  , count(dai.Date_Authorised) as numbers
  , dai.Registration_Number
  , dai.Request_Row_ID
  , dai.Specimen_Number
  , rs.Authorised_By
  , rs.Namespace
  , rs.Set_Code
  , rs.Date_Time_Authorised
  , r.Date_Time_Received
  , r.Location 
FROM 
  Date_Authorised_Index dai    
INNER JOIN Result_Set rs ON (dai.Date_Authorised = rs.Date_Authorised
                         AND dai.Request_Row_ID = rs.Request_Row_ID)
INNER JOIN Request R ON (dai.Request_Row_ID = r.Request_Row_ID)
WHERE 
  (dai.Discipline= 'C') AND rs.Set_Code=? 
GROUP BY 
  rs.Date_Booked_In

如果要一次选择100行,只需使用要选择的set_codes创建一个新表,然后加入该表。
确保将字段sc.set_code编入索引(或者更好,然后将其作为主键)

SELECT lots_of_columns
FROM table1 as dai
INNER JOIN table2 as rs ON (what you joined on before)
INNER JOIN table3 as r ON (same here)
INNER JOIN Setcodes as sc ON (sc.Set_code = rs.SetCode)  <<-- extra join.
WHERE 
  dai.discipline = 'C'
GROUP BY  rs.Date_Booked_In

或者您甚至可以使用下面的“IN(...)”,尽管它可能比连接慢。

SELECT lots_of_columns
FROM table1 as dai
INNER JOIN table2 as rs ON (what you joined on before)
INNER JOIN table3 as r ON (same here)
WHERE 
  dai.discipline = 'C' AND rs.Set_Code IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
GROUP BY  rs.Date_Booked_In