【问题标题】:Optimizing Subqueries Including Functions and Multiple Tables优化子查询,包括函数和多表
【发布时间】:2014-09-03 18:44:17
【问题描述】:

我目前有一些类似的东西:

SELECT M.ID, M.Something1, M.Something2, D1.Date, D2.Date, D3.Date
FROM MasterTable M
    LEFT JOIN DateTable1 D1
    LEFT JOIN DateTable2 D2
    LEFT JOIN DateTable3 D3
WHERE (D1.Date = (SELECT MAX(A.Date) FROM DateTable1 A WHERE A.MasterID = M.ID)
    OR D1.Date IS NULL)
AND (D2.Date = (SELECT MAX(B.Date) FROM DateTable2 B WHERE B.MasterID = M.ID)
    OR D2.Date IS NULL)
AND (D3.Date = (SELECT MAX(C.Date) FROM DateTable3 C WHERE C.MasterID = M.ID)
    OR D3.Date IS NULL)

这工作正常并且给出了正确的结果,但是它相当慢。 (还有更多的连接和更多的“东西”,但我认为它们与这里无关。)

在改进此查询的过程中,我在 WHERE 子句中发现了类似的内容:

WHERE (D1.Date, D2.Date, D3.Date) = (
    SELECT D1.Date...
    FROM DateTable1...

我不知道我发现的东西和我尝试的东西一样复杂,但一般的要点是我认为我可以在一个子查询中获取所有 3 个日期。我试过类似的东西:

WHERE (D1.Date, D2.Date, D3.Date) = (
    SELECT MAX(A.Date), MAX(B.Date), MAX(C.Date)
    FROM DateTable1 A, DateTable2 B, DateTable3 C
    WHERE... all the ids match

但那不适合我。

那么,如果不出意外,有没有办法更好地优化第一个查询?我可以将其缩小到单个子查询吗?还有其他方法可以提高性能吗?

谢谢

【问题讨论】:

  • 该元组语法在 oracle 中有效,但在 sql server 中无效。也许 MAX 函数的 OVER 子句可以在这里提供帮助。
  • 如果有,请分享表结构、示例数据和表上的索引。没有那些最完美的调优建议只是猜测。
  • 如果查询错误,它如何正常工作?例如,关键字“WHERE”附近的语法不正确

标签: sql sql-server subquery query-optimization query-performance


【解决方案1】:

我怀疑您的查询速度很慢,因为您正在为每个主 ID 获取日期的笛卡尔积。尝试使用此版本:

SELECT M.ID, M.Something1, M.Something2, D1.Date, D2.Date, D3.Date
FROM MasterTable M LEFT JOIN
     (select d.*, row_number() over (partition by masterid order by date desc) as seqnum
      from DateTable1 d
     ) D1
     on d1.masterid = m.id and d1.seqnum = 1 left join
     (select d.*, row_number() over (partition by masterid order by date desc) as seqnum
      from DateTable2 d
     ) D2
     on d2.masterid = m.id and d2.seqnum = 1 left join
     (select d.*, row_number() over (partition by masterid order by date desc) as seqnum
      from DateTable3 d
     ) d3
     on d3.masterid = m.id and d3.seqnum = 1;

【讨论】:

    【解决方案2】:

    试试这个,如果有帮助就标记

    SELECT M.ID, M.Something1, M.Something2, (SELECT MAX(A.Date) FROM DateTable1 A WHERE A.MasterID = M.ID) as 'D1Date',(SELECT MAX(B.Date) FROM DateTable2 B WHERE B.MasterID = M.ID) as 'D2Date', (SELECT MAX(C.Date) FROM DateTable3 C WHERE C.MasterID = M.ID) as 'D3Date' FROM MasterTable M 
    

    【讨论】:

      【解决方案3】:

      这是另一个使用 APPLY 的选项。

      SELECT M.ID
          , M.Something1
          , M.Something2
          , D1.Date
          , D2.Date
          , D3.Date
      FROM MasterTable M
      cross apply
      (
          select MAX(d.date) as Date
          from DateTable1 d
          where d.masterid = m.id
      ) d1
      cross apply
      (
          select MAX(d.date) as Date
          from DateTable2 d
          where d.masterid = m.id
      ) d2
      cross apply
      (
          select MAX(d.date) as Date
          from DateTable3 d
          where d.masterid = m.id
      ) d3
      

      【讨论】:

        猜你喜欢
        • 2023-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多