Как уменьшить количество похожих коррелированных подзапросов? - PullRequest
1 голос
/ 29 сентября 2011

Это часть более крупного утверждения, но мне интересно, поможет ли CTE или другой метод сделать это более эффективным или более чистым. Я мог бы написать это как табличную функцию и включить ее в мое предложение from, но я бы хотел избежать лишних объектов, если есть другое решение.

Подзапросы SELECT TOP 1 ... здесь просто перехватывают, когда у меня есть курс с более ранней датой вступления в силу, чем у базовой таблицы, но я не люблю повторять их для каждого столбца, к которому мне нужно получить доступ. Есть ли лучший способ сделать это, или это нормально выглядящее утверждение?

SELECT j.EmployeeId
       ,j.CompanyId
       ,j.JobCode
       ,COALESCE(j.CustomWageRate, r.WageRate, (SELECT TOP 1 WageRate
                                                FROM   ContractLabor.CompanyJobRates
                                                WHERE  CompanyId = j.CompanyId
                                                       AND JobCode = j.JobCode
                                                       AND EffectiveDate < j.EffectiveDate
                                                ORDER  BY EffectiveDate DESC), 0) AS EffectiveRate
       ,COALESCE(r.CustomBurdenRateReg, (SELECT TOP 1 CustomBurdenRateReg
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateReg
       ,COALESCE(r.CustomBurdenRateOvt, (SELECT TOP 1 CustomBurdenRateOvt
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateOvt
       ,COALESCE(r.CustomBurdenRateDbl, (SELECT TOP 1 CustomBurdenRateDbl
                                         FROM   ContractLabor.CompanyJobRates
                                         WHERE  CompanyId = j.CompanyId
                                                AND JobCode = j.JobCode
                                                AND EffectiveDate < j.EffectiveDate
                                         ORDER  BY EffectiveDate DESC)) AS CustomBurdenRateDbl
       ,j.EffectiveDate
FROM   ContractLabor.EmployeeJobDetails j
       LEFT JOIN ContractLabor.CompanyJobRates r
         ON j.CompanyId = r.CompanyId
            AND j.JobCode = r.JobCode
            AND j.EffectiveDate = r.EffectiveDate

Ответы [ 2 ]

3 голосов
/ 29 сентября 2011
SELECT j.EmployeeId
       ,j.CompanyId
       ,j.JobCode
       ,COALESCE(j.CustomWageRate, r.WageRate, ca.WageRate, 0) AS EffectiveRate
       ,COALESCE(r.CustomBurdenRateReg, ca.CustomBurdenRateReg) AS CustomBurdenRateReg
       ,COALESCE(r.CustomBurdenRateOvt, ca.CustomBurdenRateOvt) AS CustomBurdenRateOvt
       ,COALESCE(r.CustomBurdenRateDbl, ca.CustomBurdenRateDbl) AS CustomBurdenRateDbl
       ,j.EffectiveDate
FROM   ContractLabor.EmployeeJobDetails j
       LEFT JOIN ContractLabor.CompanyJobRates r
         ON j.CompanyId = r.CompanyId
            AND j.JobCode = r.JobCode
            AND j.EffectiveDate = r.EffectiveDate

       OUTER APPLY --or CROSS APPLY
       (
            SELECT TOP 1 WageRate
                    ,CustomBurdenRateReg
                    ,CustomBurdenRateOvt
                    ,CustomBurdenRateDbl
            FROM   ContractLabor.CompanyJobRates
            WHERE  CompanyId = j.CompanyId
                    AND JobCode = j.JobCode
                    AND EffectiveDate < j.EffectiveDate
            ORDER  BY EffectiveDate DESC       
       ) ca  
2 голосов
/ 29 сентября 2011

Вы можете присоединиться к производному табличному выражению во внешнем запросе, используя cross apply / top 1, и выбрать все соответствующие столбцы одновременно.

Ваш запрос может выглядеть следующим образом:

SELECT ..., ISNULL(x, defaultValues.x)
FROM ...
  CROSS APPLY (SELECT TOP(1) x, y, z FROM ... WHERE ... ORDER BY ...) defaultValues

Это будет более эффективно, поскольку в запросе меньше объединений (каждый из ваших исходных коррелированных подзапросов превращается во внешнее объединение).

Вы также можете использовать OUTER APPLY для функции внешнего объединения, подобной функциональности.

...