【问题标题】:Filter OUTER APPLY column in WHERE clause在 WHERE 子句中过滤 OUTER APPLY 列
【发布时间】:2016-08-28 23:19:28
【问题描述】:

我目前有一个复杂的 SQL 查询,它被插入到一个临时表中。该查询包含OUTER APPLY,因为并非所有返回的记录都将应用于结果集。

我还需要使用WHERE 子句中的OUTER APPLY 列来过滤结果,但还需要包含不适用于OUTER APPLY .e 的结果。所有外部应用结果 = 1 和非外部应用结果。

这是查询布局的简单版本:

INSERT INTO #temp (X, Y, Z, O1, O2)
SELECT 
    X Y Z
FROM T1 
INNER JOIN T2, T etc.
OUTER APPLY (
    SELECT O1, O2 FROM XYZ…) OATable
WHERE
    OATable.O1 = 1 -- I tried just adding “IN (1, NULL)” but this 
still excludes the results. 

任何帮助将不胜感激。

平台:SQL Server 2012+

谢谢

【问题讨论】:

  • 我对实际查询很感兴趣;到目前为止的答案似乎都不错,但我认为我们(潜在的回答者)不能真正根据您非常简化的查询来判断我们是否有用地回答。如果您能够发布完整的查询,请您这样做吗?它可能有助于获得更完美的答案。
  • 一些示例数据或许也会有所帮助。

标签: sql sql-server database tsql sql-server-2012


【解决方案1】:

您无法直接与NULL 进行比较,因为没有任何东西等同于NULL(甚至不等于NULL 本身)。这排除了在此处使用IN。相反,只需使用 OR 语句:

INSERT INTO #temp (X, Y, Z, O1, O2)
SELECT
    X, Y, Z,
FROM T1 
INNER JOIN T2 ON ...
OUTER APPLY (SELECT O1, O2 FROM XYZ…) OATable
WHERE
    OATable.O1 = 1 OR OATable.O1 IS NULL

假定O1XYZ 中的NOT NULL 列。

【讨论】:

  • 你测试过这个吗?我做到了。如果 01 不为空,则 OATable.O1 IS NULL 将始终为假。即使 01 可以为空,它仍然只能找到空的实际值。这不“也包括不适用于 OUTER APPLY 的结果”。
【解决方案2】:

我认为 Tom H 的回答解决了上述问题
但我认为这可能是你真正想要的

SELECT X Y Z, OATable.*
FROM T1 
INNER JOIN T2, T etc.
LEFT  JOIN XYZ as OATable 
        on OATable.O1 = 1 

在 Tom 的回答中,您需要一个文字 OATable.O1 IS NULL(根据我的发现)
如果该列被定义为不为空,则不会发生这种情况
OATable.O1 IS NULL 在外部应用中只会找到 null 的文字值,即使该列允许 null

在此答案中,您会得到左侧与 OATable O1 = 1 不匹配

【讨论】:

  • 我同意你的直觉,即 OUTER APPLY 不太可能是正确的方法,但我不确定你的理由。我认为@TomH 的答案可能会奏效,您可能会误解 OUTER APPLY 一点。 (虽然不确定!)
  • @StuartJCuthbertson 然后测试 - 我做了
  • 我绝对担心您的 LEFT JOIN 条件,它匹配一个常量,因此将匹配所有左侧行。这似乎不太可能是正确的,我认为可能隐藏在我们尚未显示的 OP 的真实查询中的连接条件。
  • @StuartJCuthbertson 完全正确 - 这可能是 OP 正在寻找的。 “我还需要使用 WHERE 子句中的 OUTER APPLY 列来过滤结果,但还需要包含不适用于 OUTER APPLY 的结果”。我说可能正在寻找。
  • 我会在我有访问权限和时间的时候进行测试,如果仍然需要的话。我认为通过披露测试结果可能会改善您的答案...
【解决方案3】:

这是你想要达到的目标吗:

CREATE TABLE #T1 ( X INT, y INT, z INT );
INSERT  INTO #T1
        ( X, y, z )
VALUES  ( 1  -- X - int
            , 2  -- y - int
            , 3  -- z - int
            );
CREATE TABLE #t2 ( a INT, b INT );
INSERT  INTO #t2
        ( a, b )
VALUES  ( 2  -- a - int
            , 5  -- b - int
            );
CREATE TABLE #xyz ( a1 INT, a2 INT );
INSERT  INTO #xyz
        ( a1, a2 )
VALUES  ( 1  -- a1 - int
            , 20  -- a2 - int
            ),
        ( NULL, 30 );

SELECT  Insertdata.X
        , Insertdata.y
        , Insertdata.z
        , Insertdata.a
        , Insertdata.b
        , Insertdata.a1
        , Insertdata.a2
INTO    #temp
FROM    ( SELECT    INQ.X
                    , INQ.y
                    , INQ.z
                    , INQ.a
                    , INQ.b
                    , O.a1
                    , O.a2
            FROM      ( SELECT    X
                                , y
                                , z
                                , a
                                , b
                        FROM      #T1
                                INNER JOIN #t2
                                ON y = a
                    ) AS INQ
                    OUTER APPLY ( SELECT    a1
                                            , a2
                                    FROM      #xyz
                                ) AS O
            WHERE     a1 = 1
                    OR a1 IS NULL
        ) AS Insertdata;

SELECT  X
        , y
        , z
        , a
        , b
        , a1
        , a2
FROM    #temp;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-26
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 2011-01-30
    • 2020-03-09
    相关资源
    最近更新 更多