【问题标题】:SQL: Deleting Identical Columns With Different NamesSQL:删除具有不同名称的相同列
【发布时间】:2022-01-15 09:07:10
【问题描述】:

我正在使用 Netezza SQL。我的原始表(“original_table”)看起来像这样(包含数字和字符变量):

  age height height2 gender gender2
1  18   76.1    76.1      M       M
2  19   77.0    77.0      F       F
3  20   78.1    78.1      M       M
4  21   78.2    78.2      M       M
5  22   78.8    78.8      F       F
6  23   79.7    79.7      F       F

我想从该表中删除具有相同条目但名称不同的列。最后,这应该是这样的(“new_table”):

  age height gender
1  18   76.1      M
2  19   77.0      F
3  20   78.1      M
4  21   78.2      M
5  22   78.8      F
6  23   79.7      F

我的问题:在 SQL 中是否有标准的方法来执行此操作?我试图做一些研究,发现了以下链接:How do I compare two columns for equality in SQL Server?

到目前为止我的尝试:似乎这样的事情可能会奏效:

CREATE TABLE new_table AS SELECT * FROM original_table;

ALTER TABLE new_table
ADD does_age_equal_height varchar(255);

    UPDATE new_table 

SET     does_age_equal_height =  CASE  
WHEN age = height THEN '1' ELSE '0' END AS does_age_equal_height;
                  

从这里开始,如果“does_age_equal_height”列中所有值的“总和”等于“new_table”中的行数(即select count(rownum) from new_table) - 这必须意味着两列相等,并且其中之一可以删除列。

但是,这是一种非常低效的方法,即使对于具有少量列的表也是如此。在我的示例中,我有 5 列 - 这意味着我必须重复上述过程“5C2”次,即 5! / (2!*3!) = 10 次。例如:

ALTER TABLE employees
  ADD does_age_equal_height varchar(255),
     does_age_equal_height2 varchar(255)
does_age_equal_gender varchar(255)
does_age_equal_gender2 varchar(255)
does_height_equal_height2 varchar(255)
does_height_equal_gender varchar(255)
does_height_equal_gender2 varchar(255)
does_height2_equal_gender varchar(255)
does_height2_equal_gender2 varchar(255)
does_gender_equal_gender2 varchar(255);

这之后会出现多个 CASE 语句 - 使过程更加复杂。

有人可以告诉我一个更有效的方法吗?

谢谢!

【问题讨论】:

  • 我很困惑 - 为什么需要比较所有列组合?您不能只检查明显重复的那些(例如,您的示例中的 height 和 height2 吗?粗略检查前几行应该足以识别可能要检查的候选人,只有 5 列。
  • @APH:谢谢你的回复!在我的真实表中有数百列和数千行。因此,我认为不可能进行粗略的检查。谢谢!
  • 对于重复的列,你应该考虑多列的值,如果我错了,请纠正我。
  • @Farshid Shekari:谢谢你的回复!我认为您需要考虑所有列值?谢谢!
  • 如果表中有两列有 10,000 行或 100 万行,并且除了 1 行之外所有列都相同,这意味着您为了 1 行而保留两列?这似乎是一种奇怪的情况。

标签: sql duplicates case alter


【解决方案1】:

我希望以正确的方式解决您的问题。这是我在 SqlServer 中的代码来处理它,你应该基于 Netezza SQL 自定义它。

我的想法是:
计算每一列的MD5,然后将这些列一起比较,如果有相同的hash,就会选择其中一列。

我将为这个问题创建下表:

CREATE TABLE Students
(
    Id INT PRIMARY KEY IDENTITY,
    StudentName VARCHAR (50),
    Course VARCHAR (50),
    Score INT,
    lastName VARCHAR (50) -- another alias for StudentName ,
    metric INT, -- another alias for score
    className VARCHAR(50) -- another alias for Course 
)
GO

INSERT INTO Students VALUES ('Sally', 'English', 95, 'Sally', 95, 'English');
INSERT INTO Students VALUES ('Sally', 'History', 82, 'Sally', 82, 'History');
INSERT INTO Students VALUES ('Edward', 'English', 45, 'Edward', 45, 'English');
INSERT INTO Students VALUES ('Edward', 'History', 78, 'Edward', 78, 'History');

创建表并插入示例记录后,轮流查找相似的列。

第 1 步。声明变量。

DECLARE @cols_q VARCHAR(max), 
        @cols VARCHAR(max), 
        @table_name  VARCHAR(max)= N'Students', 
        @res  NVARCHAR(max),
        @newCols VARCHAR(max),
        @finalResQuery VARCHAR(max);

第 2 步。生成动态查询以计算每列的哈希值。

SELECT @cols_q = COALESCE(@cols_q+ ', ','')+'HASHBYTES(''MD5'',  CONVERT(varbinary(max), (select '+ COLumn_NAME +' as t  from Students FOR XML AUTO))) as '+ COLumn_NAME,
        @cols = coalesce(@cols + ',','')+COLumn_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table_name; 
 set  @cols_q = 'select '+  @cols_q +' into ##tmp_'+ @table_name+' from '+ @table_name;

第 3 步。运行生成的查询。

 exec(@cols_q)

第 4 步。获取删除重复列的列。

  set @res = N'select  uniq_colname into ##temp_colnames
  from(
  select  max(colname) as uniq_colname from (
     select * from ##tmp_Students 
 )tt
 unpivot ( 
    md5_hash for colname in ( '+ @cols +')
 ) as tbl
 group by md5_hash
 )tr';
   exec ( @res);

第 5 步。获得最终结果

select @newCols  = COALESCE(@newCols+ ', ','')+ uniq_colname from ##temp_colnames

 set @finalResQuery = 'select '+ @newCols +' from '+ @table_name;
 exec (@finalResQuery)

【讨论】:

  • @Farshid Shekari:谢谢你的回答!这对我来说有点太高级了,目前无法理解,但总有一天我会努力做到的!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 2022-11-10
  • 1970-01-01
  • 2021-11-15
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多