NULL 값이 있는 열만 선택
모든 행에 대한 NULL 값만 포함하는 테이블의 모든 열을 선택하려면 어떻게 해야 합니까?MS SQL Server 2005를 사용하고 있습니다.표에 사용되지 않는 열을 찾아서 삭제하려고 합니다.
다음은 sql 2005 이상 버전입니다.ADDR_Address를 테이블 이름으로 바꿉니다.
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 = 'ADDR_Address'
OPEN getinfo
FETCH NEXT FROM getinfo into @col
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @cmd = 'IF NOT EXISTS (SELECT top 1 * FROM ADDR_Address WHERE [' + @col + '] IS NOT NULL) BEGIN print ''' + @col + ''' end'
EXEC(@cmd)
FETCH NEXT FROM getinfo into @col
END
CLOSE getinfo
DEALLOCATE getinfo
SELECT cols
FROM table
WHERE cols IS NULL
테이블 "사용자"에 NULL 값만 있는 모든 열 목록이 표시됩니다.결과는 여러 개의 결과 집합으로 표시되며, 이들은 비어 있거나 단일 열의 이름을 포함합니다.다른 테이블로 사용하려면 두 위치의 "사용자"를 교체해야 합니다.
DECLARE crs CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM syscolumns WHERE id=OBJECT_ID('Person')
OPEN crs
DECLARE @name sysname
FETCH NEXT FROM crs INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC('SELECT ''' + @name + ''' WHERE NOT EXISTS (SELECT * FROM Person WHERE ' + @name + ' IS NOT NULL)')
FETCH NEXT FROM crs INTO @name
END
CLOSE crs
DEALLOCATE crs
아니면 열에 NULL 값만 있는지(따라서 사용되지 않을 수 있음) 확인하고 싶으십니까?
질문에 대한 추가 설명이 도움이 될 수 있습니다.
편집: 좋아요.여기 당신을 시작하게 하는 정말 거친 코드가 있습니다...
SET NOCOUNT ON
DECLARE @TableName Varchar(100)
SET @TableName='YourTableName'
CREATE TABLE #NullColumns (ColumnName Varchar(100), OnlyNulls BIT)
INSERT INTO #NullColumns (ColumnName, OnlyNulls) SELECT c.name, 0 FROM syscolumns c INNER JOIN sysobjects o ON c.id = o.id AND o.name = @TableName AND o.xtype = 'U'
DECLARE @DynamicSQL AS Nvarchar(2000)
DECLARE @ColumnName Varchar(100)
DECLARE @RC INT
SELECT TOP 1 @ColumnName = ColumnName FROM #NullColumns WHERE OnlyNulls=0
WHILE @@ROWCOUNT > 0
BEGIN
SET @RC=0
SET @DynamicSQL = 'SELECT TOP 1 1 As HasNonNulls FROM ' + @TableName + ' (nolock) WHERE ''' + @ColumnName + ''' IS NOT NULL'
EXEC sp_executesql @DynamicSQL
set @RC=@@rowcount
IF @RC=1
BEGIN
SET @DynamicSQL = 'UPDATE #NullColumns SET OnlyNulls=1 WHERE ColumnName=''' + @ColumnName + ''''
EXEC sp_executesql @DynamicSQL
END
ELSE
BEGIN
SET @DynamicSQL = 'DELETE FROM #NullColumns WHERE ColumnName=''' + @ColumnName+ ''''
EXEC sp_executesql @DynamicSQL
END
SELECT TOP 1 @ColumnName = ColumnName FROM #NullColumns WHERE OnlyNulls=0
END
SELECT * FROM #NullColumns
DROP TABLE #NullColumns
SET NOCOUNT OFF
네, 더 쉬운 방법도 있지만, 저는 지금 당장 회의에 가야 합니다.행운을 빕니다.
다음은 2008년 이후 브라이언의 질의에 대한 업데이트 버전입니다.INFORMATION_SCHEMA.COLUM을 사용하고 테이블 스키마 및 테이블 이름에 대한 변수를 추가합니다.열 데이터 유형이 출력에 추가되었습니다.열 데이터 유형을 포함하면 특정 데이터 유형의 열을 찾는 데 도움이 됩니다.저는 열 너비나 다른 것을 추가하지 않았습니다.
출력의 경우 RAISEROR... WITH NOWAIT가 사용되므로 PRINT와 마찬가지로 텍스트가 마지막에 한 번에 모두(대부분의 경우)가 아니라 바로 표시됩니다.
SET NOCOUNT ON;
DECLARE
@ColumnName sysname
,@DataType nvarchar(128)
,@cmd nvarchar(max)
,@TableSchema nvarchar(128) = 'dbo'
,@TableName sysname = 'TableName';
DECLARE getinfo CURSOR FOR
SELECT
c.COLUMN_NAME
,c.DATA_TYPE
FROM
INFORMATION_SCHEMA.COLUMNS AS c
WHERE
c.TABLE_SCHEMA = @TableSchema
AND c.TABLE_NAME = @TableName;
OPEN getinfo;
FETCH NEXT FROM getinfo INTO @ColumnName, @DataType;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = N'IF NOT EXISTS (SELECT * FROM ' + @TableSchema + N'.' + @TableName + N' WHERE [' + @ColumnName + N'] IS NOT NULL) RAISERROR(''' + @ColumnName + N' (' + @DataType + N')'', 0, 0) WITH NOWAIT;';
EXECUTE (@cmd);
FETCH NEXT FROM getinfo INTO @ColumnName, @DataType;
END;
CLOSE getinfo;
DEALLOCATE getinfo;
할 수 있는 일:
select
count(<columnName>)
from
<tableName>
카운트가 0을 반환하면 해당 열의 모든 행이 모두 NULL(또는 테이블에 행이 전혀 없음)을 의미합니다.
로 변경 가능
select
case(count(<columnName>)) when 0 then 'Nulls Only' else 'Some Values' end
from
<tableName>
자동화하려면 시스템 테이블을 사용하여 관심 있는 테이블의 열 이름을 반복할 수 있습니다.
열이 " " " 인 NULL
그러면 저는 그것을 사용할 것입니다.COLLATE
첫 값을 합니다.값 목록을 사용하고 null이 아닌 첫 번째 값을 반환합니다.열에는 " " " 를 사용합니다.IS NULL
행을 수 .
SELECT * FROM MyTable WHERE COLLATE(Col1, Col2, Col3, Col4......) IS NULL
이 ALL로 이 있으면 안 됩니다.columns
null, 이것은 당신이 없다는 것을 의미하기 때문입니다.primary key
수 )null
기본 키가 없는 것은 피해야 할 일입니다. 이것은 첫 번째 정상적인 형태를 깨뜨립니다.
사용해 보십시오.
DECLARE @table VARCHAR(100) = 'dbo.table'
DECLARE @sql NVARCHAR(MAX) = ''
SELECT @sql = @sql + 'IF NOT EXISTS(SELECT 1 FROM ' + @table + ' WHERE ' + c.name + ' IS NOT NULL) PRINT ''' + c.name + ''''
FROM sys.objects o
JOIN sys.columns c ON o.[object_id] = c.[object_id]
WHERE o.[type] = 'U'
AND o.[object_id] = OBJECT_ID(@table)
AND c.is_nullable = 1
EXEC(@sql)
2005년에 대해서는 잘 모르겠지만 2008년에는 성공했습니다.
USE [DATABASE_NAME] -- !
GO
DECLARE @SQL NVARCHAR(MAX)
DECLARE @TableName VARCHAR(255)
SET @TableName = 'TABLE_NAME' -- !
SELECT @SQL =
(
SELECT
CHAR(10)
+'DELETE FROM ['+t1.TABLE_CATALOG+'].['+t1.TABLE_SCHEMA+'].['+t1.TABLE_NAME+'] WHERE '
+(
SELECT
CASE t2.ORDINAL_POSITION
WHEN (SELECT MIN(t3.ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS t3 WHERE t3.TABLE_NAME=t2.TABLE_NAME) THEN ''
ELSE 'AND '
END
+'['+COLUMN_NAME+'] IS NULL' AS 'data()'
FROM INFORMATION_SCHEMA.COLUMNS t2 WHERE t2.TABLE_NAME=t1.TABLE_NAME FOR XML PATH('')
) AS 'data()'
FROM INFORMATION_SCHEMA.TABLES t1 WHERE t1.TABLE_NAME = @TableName FOR XML PATH('')
)
SELECT @SQL -- EXEC(@SQL)
여기서는 모든 종류의 SQL 테이블에 대한 스크립트를 만들었습니다.이 저장 프로시저를 복사하여 환경에 만들고 테이블로 이 저장 프로시저를 실행하십시오.
exec [dbo].[SP_RemoveNullValues] 'Your_Table_Name'
저장 프로시저
GO
/****** Object: StoredProcedure [dbo].[SP_RemoveNullValues] Script Date: 09/09/2019 11:26:53 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- akila liyanaarachchi
Create procedure [dbo].[SP_RemoveNullValues](@PTableName Varchar(50) ) as
begin
DECLARE Cussor CURSOR FOR
SELECT COLUMN_NAME,TABLE_NAME,DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @PTableName
OPEN Cussor;
Declare @ColumnName Varchar(50)
Declare @TableName Varchar(50)
Declare @DataType Varchar(50)
Declare @Flage int
FETCH NEXT FROM Cussor INTO @ColumnName,@TableName,@DataType
WHILE @@FETCH_STATUS = 0
BEGIN
set @Flage=0
If(@DataType in('bigint','numeric','bit','smallint','decimal','smallmoney','int','tinyint','money','float','real'))
begin
set @Flage=1
end
If(@DataType in('date','atetimeoffset','datetime2','smalldatetime','datetime','time'))
begin
set @Flage=2
end
If(@DataType in('char','varchar','text','nchar','nvarchar','ntext'))
begin
set @Flage=3
end
If(@DataType in('binary','varbinary'))
begin
set @Flage=4
end
DECLARE @SQL VARCHAR(MAX)
if (@Flage in(1,4))
begin
SET @SQL =' update ['+@TableName+'] set ['+@ColumnName+']=0 where ['+@ColumnName+'] is null'
end
if (@Flage =3)
begin
SET @SQL =' update ['+@TableName+'] set ['+@ColumnName+'] = '''' where ['+@ColumnName+'] is null '
end
if (@Flage =2)
begin
SET @SQL =' update ['+@TableName+'] set ['+@ColumnName+'] ='+'''1901-01-01 00:00:00.000'''+' where ['+@ColumnName+'] is null '
end
EXEC(@SQL)
FETCH NEXT FROM Cussor INTO @ColumnName,@TableName,@DataType
END
CLOSE Cussor
DEALLOCATE Cussor
END
열 집합을 반복해서 확인해야 합니다.DESCRIPE table 명령을 사용하여 모든 열의 목록을 가져올 수 있어야 합니다.
유사 코드:
foreach $column ($cols) {
query("SELECT count(*) FROM table WHERE $column IS NOT NULL")
if($result is zero) {
# $column contains only null values"
push @onlyNullColumns, $column;
} else {
# $column contains non-null values
}
}
return @onlyNullColumns;
이것이 약간 직관적이지 않은 것처럼 보이지만 SQL은 열을 선택하는 기본 방법을 제공하지 않고 행만 제공합니다.
또한 NULL뿐만 아니라 모든 값이 동일한 필드를 검색하는 것이 좋습니다.
즉, 각 테이블의 각 열에 대해 쿼리를 수행합니다.
SELECT COUNT(DISTINCT field) FROM tableName
결과적으로 1을 반환하는 것에 집중합니다.
SELECT t.column_name
FROM user_tab_columns t
WHERE t.nullable = 'Y' AND t.table_name = 'table name here' AND t.num_distinct = 0;
'user2466387' 버전의 업데이트된 버전으로, null이 아닌 열을 테스트해도 소용없기 때문에 성능을 향상시킬 수 있는 작은 테스트가 추가되었습니다.
AND IS_NULLABLE = 'YES'
전체 코드:
SET NOCOUNT ON;
DECLARE
@ColumnName sysname
,@DataType nvarchar(128)
,@cmd nvarchar(max)
,@TableSchema nvarchar(128) = 'dbo'
,@TableName sysname = 'TableName';
DECLARE getinfo CURSOR FOR
SELECT
c.COLUMN_NAME
,c.DATA_TYPE
FROM
INFORMATION_SCHEMA.COLUMNS AS c
WHERE
c.TABLE_SCHEMA = @TableSchema
AND c.TABLE_NAME = @TableName
AND IS_NULLABLE = 'YES';
OPEN getinfo;
FETCH NEXT FROM getinfo INTO @ColumnName, @DataType;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = N'IF NOT EXISTS (SELECT * FROM ' + @TableSchema + N'.' + @TableName + N' WHERE [' + @ColumnName + N'] IS NOT NULL) RAISERROR(''' + @ColumnName + N' (' + @DataType + N')'', 0, 0) WITH NOWAIT;';
EXECUTE (@cmd);
FETCH NEXT FROM getinfo INTO @ColumnName, @DataType;
END;
CLOSE getinfo;
DEALLOCATE getinfo;
이건 어때?WHERE 절의 주석을 제거하여 한 테이블만 작업합니다.빈 테이블이 잘못된 긍정을 생성하므로 무시하도록 코드를 변경했습니다.테이블이 방금 작성된 경우 행 수를 입력합니다.
DROP TABLE IF EXISTS #AllColumns;
DECLARE
@All SMALLINT,
@Cur SMALLINT,
@Schema SYSNAME,
@Table SYSNAME,
@Column SYSNAME,
@SQL NVARCHAR(4000);
CREATE TABLE #AllColumns
(
ID SMALLINT IDENTITY(1,1) NOT NULL,
[Schema] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Table] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Column] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Type] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
ColumnID SMALLINT NOT NULL,
AllNull BIT NULL,
[Rows] INT NOT NULL
);
DECLARE
@Tables TABLE
(
[Schema] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Table] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Object_ID] INT NOT NULL,
[Rows] INT NOT NULL
);
BEGIN TRY
INSERT INTO @Tables( [Schema], [Table], [Object_ID], [Rows] )
SELECT SCHEMA_NAME( ST.SCHEMA_ID ) AS [Schema], ST.[Name] AS [Table], ST.OBJECT_ID, SP.[Rows]
FROM sys.tables AS ST -- 323
INNER JOIN sys.indexes AS SI ON ST.OBJECT_ID = SI.OBJECT_ID
INNER JOIN sys.partitions AS SP ON SI.OBJECT_ID = SP.OBJECT_ID AND SI.index_id = SP.index_id
GROUP BY SCHEMA_NAME( ST.SCHEMA_ID ), ST.[Name], ST.OBJECT_ID, SP.[Rows]; -- 322
INSERT INTO #AllColumns( [Schema], [Table], [Column], [Type], ColumnID, [Rows] )
SELECT ST.[Schema], ST.[Table], SC.[Name] AS [Column], TP.[Name], SC.Column_ID, ST.[Rows]
FROM @Tables AS ST
INNER JOIN sys.columns AS SC ON ST.OBJECT_ID = SC.OBJECT_ID
INNER JOIN sys.types AS TP ON SC.user_type_id = TP.user_type_id
WHERE ST.[Rows] > 0 -- AND ST.[Table] = 'Table' AND ST.[Schema] = 'dbo'
ORDER BY ST.[Schema], ST.[Table], SC.column_id;
SELECT @All = @@ROWCOUNT, @Cur = 1;
WHILE @Cur <= @All
BEGIN
SELECT
@Schema = [Schema],
@Table = [Table],
@Column = [Column]
FROM #AllColumns
WHERE ID = @Cur;
SET @SQL = '
UPDATE TC
SET AllNull = ( CASE WHEN EXISTS( SELECT 1 FROM ' + @Schema + '.' + @Table + ' WHERE ' + QUOTENAME( @Column ) + ' IS NOT NULL ) THEN 0 ELSE 1 END )
FROM #AllColumns AS TC
WHERE [Table] = ''' + @Table + ''' AND [Schema] = ''' + @Schema + ''' AND [Column] = ''' + @Column + ''';';
EXECUTE sys.sp_executeSQL @stmt = @SQL;
SET @Cur += 1;
END;
SELECT [Schema], [Table], [Column], [Rows]
FROM #AllColumns
WHERE AllNull = 1
ORDER BY [Schema], [Table], ColumnID;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH;
--DROP TABLE IF EXISTS #AllColumns;
당신은 좀 더 명확히 할 필요가 있을 것입니다.당신은 정말로 무엇을 성취하려고 노력하고 있습니까?null 값만 포함된 열 이름을 찾으려면 스키마를 반복하고 이를 기반으로 동적 쿼리를 수행해야 합니다.
당신이 어떤 DBMS를 사용하고 있는지 모르기 때문에 여기에 유사 코드를 넣겠습니다.
for each col
begin
@cmd = 'if not exists (select * from tablename where ' + col + ' is not null begin print ' + col + ' end'
exec(@cmd)
end
언급URL : https://stackoverflow.com/questions/63291/select-columns-with-null-values-only
'programing' 카테고리의 다른 글
Python Pandas:에서 CSV 파일의 첫 번째 n 행만 읽는 방법은 무엇입니까? (0) | 2023.07.06 |
---|---|
기본 클래스 장식기로 구성 요소 장식기 확장 (0) | 2023.07.06 |
react import 문에서 @ 기호는 무엇을 의미합니까? (0) | 2023.07.01 |
Mac OS X v10.9(Mavericks)의 터미널에서 apt-get 기능이 작동하지 않는 이유는 무엇입니까? (0) | 2023.07.01 |
상업용 MongoDB (0) | 2023.07.01 |