首页 > 解决方案 > 引用父别名时将外部应用转换为左连接

问题描述

我目前正在尝试将外部应用转换为左连接以节省一些复杂性。

SELECT *
FROM fact_table h
     OUTER APPLY (SELECT TOP 1
                         *
                  FROM dimension mcc WITH (NOLOCK)
                  WHERE h.product = mcc.product
                    AND h.country = mcc.country
                    AND mcc.date IN (SELECT MAX(date)
                                     FROM dimension dd WITH (NOLOCK)
                                     WHERE FORMAT(DATEADD(MONTH, -3, dd.date), 'yyyyMM') <= h.month_in_the_year
                                       AND dd.product = h.product
                                       AND dd.country = h.country)) a;

我基本上用它来从 Dimension 中获取相关数据,这些数据与 3 个月前的最新数据点相关联。

我试图把它变成一个左连接,但它需要更多的时间,因为我没有在连接之前过滤维度:

SELECT TOP 10
       *
FROM fact_table h
     LEFT JOIN dimension a ON h.product = a.product
                          AND h.country = a.country
                          AND a.pkid = (SELECT TOP 1
                                               pkid
                                        FROM dimension dd
                                        WHERE FORMAT(DATEADD(MONTH, -3, dd.date), 'yyyyMM') <= h.month_in_the_year
                                        ORDER BY date DESC);

您是否知道如何有效地将其转换为左连接?

标签: sqlsql-servertsql

解决方案


看起来您可以通过简单地添加一个ORDER BY. 我还修改了日期过滤器以正确利用索引。

SELECT *
FROM fact_table h
OUTER APPLY (
    SELECT TOP 1 *
    FROM dimension mcc
    WHERE h.product = mcc.product
      AND h.country = mcc.country
      AND mcc.date < DATEADD(MONTH, 2, DATEFROMPARTS(LEFT(h.month_in_the_year, 4), RIGHT(h.month_in_the_year, 2), 1))
    ORDER BY mcc.date DESC
) a;

要将其转换为LEFT JOIN,您需要利用行编号

SELECT *
FROM (
    SELECT *,
      rn = ROW_NUMBER() OVER (PARTITION BY h.PrimaryKeyColumn ORDER BY mcc.date)
    FROM fact_table h
    LEFT JOIN dimension mcc
      ON h.product = mcc.product
        AND h.country = mcc.country
        AND mcc.date < DATEADD(MONTH, 2, DATEFROMPARTS(LEFT(h.month_in_the_year, 4), RIGHT(h.month_in_the_year, 2), 1))
) a
WHERE rn = 1;

推荐阅读