Sql 如果列存在,请选择columnValue,否则为null

Sql 如果列存在,请选择columnValue,否则为null,sql,sql-server,select,exists,Sql,Sql Server,Select,Exists,我想知道如果列存在,是否可以选择该列的值,否则只选择null。换句话说,我希望提升select语句来处理列不存在的情况 SELECT uniqueId , columnTwo , /*WHEN columnThree exists THEN columnThree ELSE NULL END*/ AS columnThree FROM (subQuery) s 注意,我正处于巩固我的数据模型和设计的中间。我希望在接下来的几周内排除这种逻辑,但我真的想超越这个问题,因为数据模

我想知道如果列存在,是否可以选择该列的值,否则只选择null。换句话说,我希望提升select语句来处理列不存在的情况

SELECT uniqueId
    ,  columnTwo
    ,  /*WHEN columnThree exists THEN columnThree ELSE NULL END*/ AS columnThree
FROM (subQuery) s
注意,我正处于巩固我的数据模型和设计的中间。我希望在接下来的几周内排除这种逻辑,但我真的想超越这个问题,因为数据模型修复比我现在想要解决的更耗时

另外请注意,我希望能够在一个查询中实现这一点。所以我不是在寻找这样的答案

首先检查子查询上的列。然后修改您的 查询以适当地处理子查询中的列


使用简单的SQL语句无法做到这一点。除非表中的所有表和列引用都存在,否则不会编译SQL查询

如果子查询是表引用或视图,则可以使用动态SQL执行此操作

在动态SQL中,您可以执行以下操作:

declare @sql nvarchar(max) = '
SELECT uniqueId, columnTwo, '+
    (case when exists (select *
                       from INFORMATION_SCHEMA.COLUMNS 
                       where tablename = @TableName and
                             columnname = 'ColumnThree' -- and schema name too, if you like
                      )
          then 'ColumnThree'
          else 'NULL as ColumnThree'
     end) + '
FROM (select * from '+@SourceName+' s
';

exec sp_executesql @sql;
对于实际的子查询,可以通过检查子查询是否返回具有该列名的内容来近似相同的内容。一种方法是运行查询:从s中选择top 0*into temp,然后检查temp中的列

编辑:

我通常不会更新这些老问题,但基于下面的评论。如果子查询中的每一行都有唯一标识符,则可以运行以下操作:

select t.. . .,  -- everything but columnthree
       (select column3   -- not qualified!
        from t t2
        where t2.pk = t.pk
       ) as column3
from t cross join
     (values (NULL)) v(columnthree);

如果外部查询不存在,子查询将从外部查询中提取第3列。然而,这在很大程度上取决于每一行都有一个唯一的标识符。问题是关于子查询的,没有理由期望行可以很容易地唯一标识。

正如其他人所建议的,合理的方法是使用符合表设计的查询

不过,有一种非常奇特的方法可以在纯SQL而非动态SQL中实现您想要的功能。在DBA.SE上发布了一个类似的问题:但它更简单,因为结果只需要一行和一列。您的问题更复杂,因此查询更复杂,至少可以这么说。以下是疯狂的做法:

; WITH s AS
  (subquery)                                    -- subquery
SELECT uniqueId
    ,  columnTwo
    ,  columnThree =
       ( SELECT ( SELECT columnThree 
                  FROM s AS s2
                  WHERE s2.uniqueId = s.uniqueId
                ) AS columnThree
         FROM (SELECT NULL AS columnThree) AS dummy
       )
FROM s ;
它还假设uniqueId在子查询的结果集中是唯一的

测试时间

还有一种更简单的方法,它还有一个额外的优点,即允许使用单个子查询执行多个列:

SELECT s.*     
FROM
    ( SELECT NULL AS columnTwo,
             NULL AS columnThree,
             NULL AS columnFour
    ) AS dummy 
  CROSS APPLY
    ( SELECT 
          uniqueId,
          columnTwo,
          columnThree,
          columnFour
      FROM tableX
    ) AS s ;
这个问题也在DBA.SE上被问到,并通过交叉应用得到了回答!并使用XML:
您可以使用动态SQL

首先需要检查exist列,然后创建动态查询

DECLARE @query NVARCHAR(MAX) = '
SELECT FirstColumn, SecondColumn, '+
  (CASE WHEN exists (SELECT 1 FROM syscolumns 
  WHERE name = 'ColumnName' AND id = OBJECT_ID('TableName'))
      THEN 'ColumnName'
      ELSE 'NULL as ThreeColumn'
   END) + '
FROM TableName'

EXEC sp_executesql @query;

我不这么认为。出于好奇,我该如何使用动态SQL?您将SQL语句构建为字符串,然后使用exec命令执行构建的字符串。根据我对动态SQL的理解,这不需要两个查询吗?对,您需要一个查询来查看字段是否存在以及是否存在,在动态查询中附加一个字符串,然后执行。@Gordon+1虽然可以完成,但请使用交叉应用程序查看我的答案为什么编写的代码假定数据模型将为零?为什么不为现在存在的列编写代码,当ColumnThree成为数据模型中的永久一等公民时,修复查询?另外,我强烈建议不要告诉别人你不想要什么。你所说的限制是不可能满足的,你需要给出一个更好的理由。当您可以将内容封装到存储过程中时,在一个查询中进行查询没有什么意义。@AaronBertrand您问了两个问题,所以我将同时回答这两个问题。首先,我的目标是尽快发布一个高质量的特性。现在我需要ColumnThree中的值(当它们存在时),以使我的功能正常工作。所以,当这个专栏存在时,我将使用它……即使这个解决方案并不完美。@AaronBertrand第二,我感谢你的建议,但我不同意。我想清楚地表达我的需求,这样用户就可以专注于提出解决我问题的解决方案,而不必浪费时间来写我知道不满意的答案。我认为明确指出哪些答案不令人满意,有助于用户关注更有价值的解决方案。这很酷!有没有一种方法可以在不进行更多联接的情况下使用多个列来完成此操作?感谢您的快速回复!不幸的是,我使用的是SAP Hana,它没有交叉应用。你能想出一个替代方案吗?我发现了这个,但我不确定它是否会起作用。@surjikal我不知道这个答案会起什么作用。我不熟悉SAP Hana,因此无法回答。您使用的是哪个版本,它背后的DBMS是什么?数据库管理系统是称为SAP Hana还是与另一个数据库管理系统通信。如果您能找到产品的SQL文档,它会有所帮助。一些数据库具有交叉/外部应用,其他数据库具有类似的横向连接。您还可以发布另一个问题,标记为
SAP Hana可以在这里使用,也可以在dba.stackexchange.com上使用。如果需要,请包含指向此问题的链接@伊佩尔切布ᵀᴹ . . . 这非常聪明,使用范围规则来处理不存在的列。荣誉SAP Hana是DBMS,它似乎不太支持SQL扩展。它具有大多数常规连接,但不幸的是没有交叉/外部应用或横向连接。文件如下: