当前位置: 首页 > 面试题库 >

使用SQL Server选择非空列

吴星汉
2023-03-14
问题内容

我正在使用SQL Server2012。我有一个包含90列的表。我试图仅选择包含数据的列。搜索后,我使用以下过程:

1-使用一个选择查询获取所有列的计数

2-将结果表转换为临时表

3-创建选择查询

4-执行此查询

这是我使用的查询:

DECLARE @strTablename  varchar(100) = 'dbo.MyTable'
DECLARE @strQuery  varchar(max) = ''
DECLARE @strSecondQuery  varchar(max) = 'SELECT '
DECLARE @strUnPivot as varchar(max) = ' UNPIVOT ([Count] for [Column] IN ('

CREATE TABLE ##tblTemp([Column] varchar(50), [Count]  Int)

SELECT @strQuery = ISNULL(@strQuery,'') + 'Count([' + name + ']) as [' + name + ']  ,' from sys.columns where object_id = object_id(@strTablename) and is_nullable = 1
SELECT @strUnPivot = ISNULL(@strUnPivot,'') + '[' + name + '] ,' from sys.columns where object_id = object_id(@strTablename) and is_nullable = 1


SET @strQuery = 'SELECT [Column],[Count] FROM ( SELECT ' + SUBSTRING(@strQuery,1,LEN(@strQuery) - 1) + ' FROM ' + @strTablename + ') AS p ' + SUBSTRING(@strUnPivot,1,LEN(@strUnPivot) - 1) + ')) AS unpvt '

INSERT INTO ##tblTemp EXEC (@strQuery)

SELECT @strSecondQuery = @strSecondQuery + '[' + [Column] + '],'  from ##tblTemp WHERE [Count] > 0

DROP TABLE ##tblTemp

SET @strSecondQuery = SUBSTRING(@strSecondQuery,1,LEN(@strSecondQuery) - 1) + ' FROM ' + @strTablename

EXEC (@strSecondQuery)

问题是此查询太慢。是否有实现此目标的最佳方法?

笔记:

  • 该表在主键Column上只有一个聚集索引,ID并且不包含任何其他索引。
  • 表格不可编辑。
  • 该表包含非常大的数据。
  • 查询大约需要1分钟才能执行

提前致谢。


问题答案:

我不知道这是否更快,但是您可能会使用一个技巧:FOR XML AUTO将省略没有内容的列:

DECLARE @tbl TABLE(col1 INT,col2 INT,col3 INT);
INSERT INTO @tbl VALUES (1,2,NULL),(1,NULL,NULL),(NULL,NULL,NULL);

SELECT * 
FROM @tbl AS tbl
FOR XML AUTO

结果col3是:丢失了…

<tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />

知道了这一点,您可以找到所有行中都不为NULL的列列表,如下所示:

DECLARE @ColList VARCHAR(MAX)=
STUFF
(
    (
    SELECT DISTINCT ',' + Attr.value('local-name(.)','nvarchar(max)')
    FROM
    (
        SELECT
        (
            SELECT *
            FROM @tbl AS tbl
            FOR XML AUTO,TYPE
        ) AS TheXML
    ) AS t
    CROSS APPLY t.TheXML.nodes('/tbl/@*') AS A(Attr) 
    FOR XML PATH('')
    ),1,1,''
);

SELECT @ColList

的内容@ColList是现在col1,col2。您可以在动态创建的字符串中放置此字符串SELECT

更新:提示

将替换为排除所有 not-nullableSELECT *创建的列列表将是非常聪明的。并且-如果需要并且可能的话-
类型包含非常大的数据(BLOB)。INFORMATION_SCHEMA.COLUMNS __

UPDATE2:性能

不知道您的 大数据 实际上意味着什么…只需在具有约500.000行(带有SELECT *)的表上进行尝试,然后在不到一分钟的时间内正确返回。希望这足够快…



 类似资料:
  • 我不希望第一项被自动选中。 我该怎么做? 尝试 没起作用

  • 本文向大家介绍怎么使用css选择空链接?相关面试题,主要包含被问及怎么使用css选择空链接?时的应答技巧和注意事项,需要的朋友参考一下

  • 作为 LINQ 查询的一部分,我有一系列列,其中只有一列将包含一个值,如何将该单个值分配给变量而不必执行类似操作 类似于这个问题,但用LINQ代替SQL。 不幸的是,用SQL处理数据库端的任何事情都不是一个选项。

  • 问题内容: 我是AngularJS的新手。我进行了很多搜索,但是并不能解决我的问题。 我第一次在选择框中得到一个空白选项。 这是我的HTML代码 JS 但这似乎不起作用。我该如何解决?这是JSFiddle演示 问题答案: 当传递给的一组选项中不存在被引用的值时,将生成空值。这样做是为了防止意外选择模型:AngularJS可以看到初始模型是未定义的还是未在选项集中,并且不想自行决定模型的值。 简而言

  • 问题内容: 我有一个大于1000万行的巨大表。我需要从中有效地获取5000个随机样本。我有一些限制因素,使我想要的总行数减少到9密耳。 我尝试通过NEWID()使用order,但是该查询将花费很长时间,因为它必须对所有行进行表扫描。 有没有更快的方法可以做到这一点? 问题答案: 如果您可以使用伪随机抽样并且您使用的是SQL Server 2005/2008,则请看一下TABLESAMPLE。例如,

  • 在Postgres9.5中,我无法从JSONB字段中的属性中选择非空值 我还尝试使用NotNull。 当我运行其中一个时,我收到错误42883。“错误:运算符不存在。JSONB->>布尔提示:没有与给定名称和参数类型匹配的运算符。您可能需要添加显式类型转换。”