在我的表 table1 中,有6列地点,a,b,c,d,e。
Locations [a] [b] [c] [d] [e]
[1] 10.00 Null Null 20.00 Null
[2] Null 30.00 Null Null Null
我需要像
这样的结果Locations [a] [b] [d]
[1] 10.00 Null 20.00
[2] Null 30.00 Null
我的问题是如何使用sql查询检测和删除包含所有空值的列。 有可能吗?
如果是,请帮助并提供样品。
答案 0 :(得分:5)
这是一个快速(且丑陋)的存储过程,它获取表的名称并打印(或者如果你想要的话,删除)充满空值的字段。
ALTER procedure mysp_DropEmptyColumns
@tableName nvarchar(max)
as begin
declare @FieldName nvarchar(max)
declare @SQL nvarchar(max)
declare @CountDef nvarchar(max)
declare @FieldCount int
declare fieldNames cursor local fast_forward for
select c.name
from syscolumns c
inner join sysobjects o on c.id=o.id
where o.xtype='U'
and o.Name=@tableName
open fieldNames
fetch next from fieldNames into @FieldName
while (@@fetch_status=0)
begin
set @SQL=N'select @Count=count(*) from "'+@TableName+'" where "'+@FieldName+'" is not null'
SET @CountDef = N'@Count int output';
exec sp_executeSQL @SQL, @CountDef, @Count = @FieldCount output
if (@FieldCount=0)
begin
set @SQL = 'alter table '+@TableName+' drop column '+@FieldName
/* exec sp_executeSQL @SQL */
print @SQL
end
fetch next from fieldNames into @FieldName
end
close fieldNames
end
这使用了一个游标,并且有点慢和复杂,但我怀疑这是一种你经常运行的程序
答案 1 :(得分:2)
SQL更多的是关于行而不是列。
如果您正在讨论删除c为null的行,请使用:
delete from table1 where c is null
如果您正在讨论当该列的所有行都为空时删除列,我会找到一个时间,您可以从用户锁定数据库并执行以下操作之一:
select c from table1 group by c
select distinct c from table1
select count(c) from table1 where c is not null
然后,如果你只返回NULL(或最后一个为0),编织你的魔法(SQL Server命令可能不同):
alter table table1 drop column c
为您想要的任何列执行此操作。
如果你要删除列,你真的需要小心。尽管它们可能充满了空值,但可能存在使用该列的SQL查询。删除列会破坏这些查询。
答案 2 :(得分:2)
如何检测给定列是否只有NULL
值:
SELECT 1 -- no GROUP BY therefore use a literal
FROM Locations
HAVING COUNT(a) = 0
AND COUNT(*) > 0;
结果集将由零行组成(列a
具有非NULL
值)或一行(列a
仅具有NULL
值)。 FWIW此代码是标准SQL-92。
答案 3 :(得分:1)
SELECT * FROM table1 WHERE c IS NOT NULL -- or also SELECT COUNT(*)
要检测此列是否确实没有值。
ALTER TABLE table1 DROP COLUMN c
如果认为需要,是删除列的查询。
答案 4 :(得分:1)
alter proc USP_DropEmptyColumns
@TableName varchar(255)
as
begin
Declare @col varchar(255), @cmd varchar(max)
DECLARE getinfo cursor for
SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID
WHERE t.Name = @TableName
OPEN getinfo
FETCH NEXT FROM getinfo into @col
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @cmd = 'IF NOT EXISTS (SELECT top 1 * FROM [' + @TableName + '] WHERE [' + @col + '] IS NOT NULL)
BEGIN
ALTER TABLE [' + @TableName + '] DROP Column [' + @col + ']
end'
EXEC(@cmd)
FETCH NEXT FROM getinfo into @col
END
CLOSE getinfo
DEALLOCATE getinfo
end
答案 5 :(得分:0)
PROC PRINT DATA=TABLE1;RUN;
PROC TRANSPOSE DATA=TABLE1 OUT=TRANS1;VAR A B C D E;RUN;
DATA TRANS2;SET TRANS1;IF COL1 = . AND COL2 = . THEN DELETE;RUN;
PROC TRANSPOSE DATA=TRANS2 OUT=TABLE2 (DROP=_NAME_);VAR COL1-COL2;RUN;
PROC PRINT DATA=TABLE2;RUN;