0

我在 DB2 sql 中遇到了一个奇怪的行为。(DB2 9.7) Follow 是一个示例查询,用于获取员工工资、状态和乐队。

SELECT
                EMP.STATUS,
                COUNT(*)               AS EMP_COUNT,
                GRP.GROUP_NAME
FROM
                EMPLOYEE EMP,
                EMPLOYEE_SALARY ES,
                GROUP_TABLE GRP
WHERE
                EMP.SALARY > 
                             (select max(EMP1.SALARY) from  
                             EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
                              date(EMP1.JOIN_DT) = '2013-01-01' 
                              and date(EMP1.DATE_TS) = date(FY.CURRENT_DT) - 2 days)
                AND EMP.SALARY = E.EMPID
                AND E.SALARY_GRP = GRP.BAND_GROUP
                AND GRP.RANGE_SALARY = 'BAND-10'
                GROUP BY
                        EMP.STATUS,
                        GRP.GROUP_NAME

EMP(员工)表包含大约 100 万行。其余的桌子都很小。查询大约需要 10 秒来执行

但是当我对内部查询进行硬编码时

select max(EMP1.SALARY) from  EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
        date(EMP1.JOIN_DT) = '2013-01-01' 
        and date(EMP1.DATE_TS) = date(FY.CURRENT_DT) - 2 days

select max(EMP1.SALARY) from  EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
       date(EMP1.JOIN_DT) = '2013-01-01' 
       and date(EMP1.DATE_TS) = '2013-06-01' 

结果在一秒钟之内!

“FINANCIAL_YEAR FY”表是一个非常小的表,大约有 50 行,因此我不知道为什么内部查询在动态时需要时间,但在我硬编码时非常快

一些附加信息

  • EMPID 是整数
  • DATE_TS 是时间戳
  • CURRENT_DT,JOIN_DT 是日期
  • 其余都是 VARCHAR
  • EMPID 已编入索引
4

1 回答 1

0

你可以试试这个版本(我假设E引用应该是ES别名,否则语句不应该运行)。除其他外,您应该放弃“隐式连接”(逗号分隔FROM子句),尤其是当您开始处理LEFT JOINs 时。

WITH Maximum_Salary (max) as (SELECT MAX(EMP.SALARY) 
                              FROM EMPLOYEE EMP
                              JOIN FINANCIAL_YEAR FY
                                ON (FY.CURRENT_DT - 2 DAYS) >= EMP.DATE_TS
                                   AND (FY.CURRENT_DT - 1 DAYS) < EMP.DATE_TS
                              WHERE EMP.JOIN_DT = DATE('2013-01-01')

SELECT EMP.STATUS, COUNT(*) AS EMP_COUNT, GRP.GROUP_NAME
FROM EMPLOYEE EMP
JOIN GROUP_TABLE GRP
  ON GRP.RANGE_SALARY = 'BAND-10'
JOIN EMPLOYEE_SALARY ES
  ON ES.EMPID = EMP.SALARY
     AND ES.SALARY_GRP = GRP.BAND_GROUP
JOIN Maximum_Salary 
  ON Maximum_Salary <= EMP.SALARY
GROUP BY EMP.STATUS, GRP.GROUP_NAME

如果您还不习惯它们,那么WITH语法就是公用表表达式(或 CTE)——实际上,它是一个内联视图。在某些情况下,这些可能会导致创建临时表,但否则可以为您节省大量输入(它们也是执行递归查询的方式)。我已经设法将对的引用EMP.DATE_TS放入可以使用索引的表单中(对日期数学没有帮助FY.CURRENT_DT,尽管作为一个不重要的小表)。

请注意,您可能仍需要执行额外的调整,尤其是取决于您可能(没有)拥有的索引。

于 2013-06-03T17:26:39.497 回答