在VIEW内的CTE中使用VIEW中的表进行内联SELECT

时间:2014-05-08 02:40:33

标签: sql tsql sql-server-2008-r2

您好我想创建一个VIEW,里面有CTE,这是我的原始查询(简化):

SELECT  ISNULL(( SELECT col_a
                 FROM   Table_A a
                 WHERE  a.id = b.id
               ), 'N/A') ,
        b.*
FROM    Table_B b

如果我想将其转换为带有CTE的VIEW,我收到错误The multi-part identifier "b.id" could not be bound. 这是我试过的

CREATE VIEW my_view
AS
    WITH    my_CTE
              AS ( SELECT   ISNULL(( SELECT col_a
                                     FROM   Table_A a
                                     WHERE  a.id = b.id
                                   ), 'N/A') my_col
                 )
    SELECT  ( SELECT    *
              FROM      my_CTE
            ) CTE_col ,
            b.*
    FROM    Table_B b

请注意,要求是让ISNULL进入CTE,但这意味着a.id是CTE内部的内联查询,这意味着我无法在视图的SELECT中执行WHERE子句。

3 个答案:

答案 0 :(得分:1)

这是查询:

WITH my_CTE AS (
      SELECT ISNULL((SELECT col_a
                     FROM Table_A a
                     WHERE a.id = b.id
                    ), 'N/A'
                   ) my_col
     )
SELECT (SELECT * FROM my_CTE) CTE_col, b.*
FROM Table_B b;

CTE在子查询中引用b。它没有在那时定义。您无法在CTE中拆分相关子查询。

您可以使用cross apply

执行您想要的操作
SELECT my_CTE.my_col CTE_col, b.*
FROM Table_B b CROSS APPLY
     (SELECT ISNULL((SELECT col_a
                     FROM Table_A a
                     WHERE a.id = b.id
                    ), 'N/A'
                   ) my_col
     ) my_CTE

还有其他方法可以简化您的特定查询,但这可能会解决您的大问题。

答案 1 :(得分:1)

我会删除CTE中的WHERE子句,然后加入CTE和Table_B。它应该是这样的:

CREATE VIEW my_view
AS
    WITH    my_CTE
              AS ( SELECT   my_col = ISNULL(col_a, 'N/A') ,
                            a.id
                   FROM     Table_A a
                 )
    SELECT  CTE_col = my_CTE.my_col ,
            b.*
    FROM    Table_B b
            JOIN my_CTE ON b.id = my_CTE.id

编辑:

到目前为止,我从未与FOR XML PATH合作过,所以我不确定这是否是你想要的。 这是一个用于连接两个表的CTE和一个仅用于XML的CTE。

也许JOIN需要LEFT JOIN,但这取决于您的数据 如果Table_A始终具有相应的ID且col_a可以为空,则INNER JOIN就足够了。
如果您想在N/A中为不存在的记录显示Table_A,则需要LEFT JOIN

CREATE VIEW my_view
AS
    WITH    my_CTE
              AS ( SELECT   my_col = ISNULL(a.col_a, 'N/A') ,
                            b.*
                   FROM     Table_A a
                            INNER JOIN Table_B b ON a.id = b.id
                 ),
            xml_cte
              AS ( SELECT   my_col
                   FROM     my_CTE
                   FOR      XML PATH
                 )
    SELECT  *
    FROM    my_CTE

答案 2 :(得分:1)

替代: (下面的代码已经完成了。发布的问题类似于https://meta.stackexchange.com/q/185681的评论中的讨论。我实际上无法在不留下文本中的SO链接的情况下发布答案。我道歉。)

WITH my_CTE(b_id, col_A) AS
(
          SELECT b.id, ISNULL(a.col_a, 'N/A')
            FROM Table_B b
 LEFT OUTER JOIN Table_A a ON b.id = a.id
)
        SELECT my_CTE.col_A, b.*
          FROM Table_B b
    INNER JOIN my_CTE ON b.id = my_CTE.b_id