SQL删除DUP并保留较长的列值

SQL删除DUP并保留较长的列值,sql,sas,Sql,Sas,我对SAS上的SQL有疑问,问题类似于下面的问题 ID|LName|FName|Address 1 |A |B |1 Street 1 |A |B |1 Street **APT 101** 2 |A |B |1 Street 2 |A |B |1 Street **APT 101** 是否可以先检查ID,然后如果地址比另一个地址长,则保留较长的地址 这是一个非常棘手的问题,但您可以: select t.* from t where t.addr

我对SAS上的SQL有疑问,问题类似于下面的问题

ID|LName|FName|Address
1 |A    |B    |1 Street
1 |A    |B    |1 Street **APT 101**
2 |A    |B    |1 Street
2 |A    |B    |1 Street **APT 101**
是否可以先检查ID,然后如果地址比另一个地址长,则保留较长的地址



这是一个非常棘手的问题,但您可以:

select t.*
from t
where t.address = (select t2.address
                   from t t2
                   where t2.id = t.id
                   order by length(t2.address) desc
                  );

这是一个很大的难题,但您可以:

select t.*
from t
where t.address = (select t2.address
                   from t t2
                   where t2.id = t.id
                   order by length(t2.address) desc
                  );

您可以根据地址列的长度对数据进行行号和排序。

应该是这样的:

select id 
    ,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Length(address) DESC)
    ,LName
    ,FName
    ,Address
from table_name;

然后只需按行数=1进行筛选。

您可以按地址列的长度对数据进行行数筛选和排序。

应该是这样的:

select id 
    ,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Length(address) DESC)
    ,LName
    ,FName
    ,Address
from table_name;

然后只需对行数=1进行筛选。

这是另一种选择。一个简单的MAX和group by应该可以做到这一点:

SELECT id, lname, fname, max(address)
FROM test WHERE 1=1
GROUP BY id, lname, fname;

警告:请记住,这将适用于具有相同“基”地址和额外文本的行。例如:

insert into test values(1, 'A', 'B', '1 Street'); 
insert into test values(1, 'A', 'B', '1 Street APT 101'); 
insert into test values(1, 'A', 'B', '1 Street APT 101 Other APT 202'); 
insert into test values(1, 'A', 'B', '1 Street APT 101 Other APT 202 yet another APT 333');
etc.
但是,如果更改行上的基址,它将“失败”:

insert into test values(1, 'A', 'B', '1 Street APT 101'); 
insert into test values(1, 'A', 'B', '1 Street APT 2'); # This is shorter but will come up instead of the other.
然而,这将是两个不同的地址,而不是有额外信息的同一个地址。因此,不管怎样,丢弃其中的任何一个都是没有意义的

如果此限制不适用于输入数据,则可以安全地使用SQL

如果您需要一个通过检查长度工作的SQL,那么下一个SQL将在mysql、mariadb和SQLite上工作。你必须检查你的数据库管理系统

SELECT id, lname, fname, address, max(t.len)
FROM (
  SELECT *, length(address) as len FROM test
  ORDER BY len DESC
  ) t
GROUP BY id, lname, fname

另一个备选方案见演示。一个简单的MAX和group by应该可以做到这一点:

SELECT id, lname, fname, max(address)
FROM test WHERE 1=1
GROUP BY id, lname, fname;

警告:请记住,这将适用于具有相同“基”地址和额外文本的行。例如:

insert into test values(1, 'A', 'B', '1 Street'); 
insert into test values(1, 'A', 'B', '1 Street APT 101'); 
insert into test values(1, 'A', 'B', '1 Street APT 101 Other APT 202'); 
insert into test values(1, 'A', 'B', '1 Street APT 101 Other APT 202 yet another APT 333');
etc.
但是,如果更改行上的基址,它将“失败”:

insert into test values(1, 'A', 'B', '1 Street APT 101'); 
insert into test values(1, 'A', 'B', '1 Street APT 2'); # This is shorter but will come up instead of the other.
然而,这将是两个不同的地址,而不是有额外信息的同一个地址。因此,不管怎样,丢弃其中的任何一个都是没有意义的

如果此限制不适用于输入数据,则可以安全地使用SQL

如果您需要一个通过检查长度工作的SQL,那么下一个SQL将在mysql、mariadb和SQLite上工作。你必须检查你的数据库管理系统

SELECT id, lname, fname, address, max(t.len)
FROM (
  SELECT *, length(address) as len FROM test
  ORDER BY len DESC
  ) t
GROUP BY id, lname, fname

请参阅演示

OVER/PARTITION在SAS SQLOVER中无效/PARTITION在SAS SQLYes中无效是的,请参阅@Julio的解决方案,该解决方案可能是最简单的。SQL中的MAX()用于字符变量。这假设您没有多个类似的地址,并且不需要一个,否则它可能无法按预期工作。长度真的是您想要验证地址的方式吗?是的,这是可能的,请参阅@Julio的解决方案,这可能是最简单的。SQL中的MAX()用于字符变量。这假设您没有多个类似的地址,并且不需要一个,否则它可能无法按预期工作。长度真的是你想要验证地址的方式吗?如果一个地址有两个文本,即APT 001和APT 10呢?那么它将可耻地失败:)。然而,给定示例输入,重复的行似乎不是这样的,相同的基础上有额外的文本。让我们看看OP是怎么说的。我将在我的数据库中的回答中添加警告,这些地址更像是1街,1街公寓,有时是1国王大道和1国王大道。我想max(address)会成功的,但我必须先测试一下!谢谢如果一个地址有两个文本,即APT 001和APT 10,该怎么办。然而,给定示例输入,重复的行似乎不是这样的,相同的基础上有额外的文本。让我们看看OP是怎么说的。我将在我的数据库中的回答中添加警告,这些地址更像是1街,1街公寓,有时是1国王大道和1国王大道。我想max(address)会成功的,但我必须先测试一下!谢谢