Had*_*adi 0 sql t-sql sql-server query-optimization sql-server-2012
我使用的是SQL Server 2012.我有一个包含90列的表.我试图只选择包含数据的列.搜索后,我使用以下程序:
1-使用一个选择查询获取所有列数
2-将结果表旋转到Temp表中
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)
Run Code Online (Sandbox Code Playgroud)
问题是这个查询太慢了.有没有最好的方法来实现这一目标?
笔记:
ID并且不包含任何其他索引.提前致谢.
我不知道这是否更快,但你可能会使用一个技巧: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
Run Code Online (Sandbox Code Playgroud)
这是结果:col3缺少......
<tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />
Run Code Online (Sandbox Code Playgroud)
知道这一点,你可以找到所有行中不是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
Run Code Online (Sandbox Code Playgroud)
的内容@ColList是现在col1,col2.这个字符串可以放在动态创建的中SELECT.
SELECT *用一个INFORMATION_SCHEMA.COLUMNS排除所有不可空的列列表替换它是非常聪明的.并且 - 如果需要和可能 - 类型,包含非常大的数据(BLOB).
不知道你的大数据实际意味着什么...只是在一个有大约500.000行(带SELECT *)的表上试过这个并且在不到一分钟后它正确返回.希望,这足够快......