通过仅选择具有最小长度值的行来删除重复行

时间:2013-08-02 14:30:50

标签: sql sql-server

我有一个包含两个字符串列的表:NameCodeCode是唯一的,但Name不是。样本数据:

Name      Code
--------  ----
Jacket    15
Jeans     003
Jeans     26

我想选择Code值最小的唯一行,但不是数值;相反,字符串的长度。当然这不起作用:

SELECT Name, Min(Code) as Code
FROM Clothes
GROUP BY Name, Code

以上代码将为牛仔裤返回一行,如下所示:

Jeans | 003

这是正确的,因为作为一个数字,003小于26。但不是在我的应用程序中,它关注值的长度,而不是实际值。长度为三个字符的值大于具有两个字符的值。我实际上需要它来回复:

Jeans | 26

因为26长度003长度短。

那么我该如何编写SQL代码来选择具有最小长度代码的行,而不是实际的最小值?我试过这样做:

SELECT Name, Min(Len(Code)) as Code
FROM Clothes
GROUP BY Name, Code

以上只返回一个字符,所以我最终得到了这个:

Jeans | 2

3 个答案:

答案 0 :(得分:4)

;WITH cte AS
(
  SELECT Name, Code, rn = ROW_NUMBER()
    OVER (PARTITION BY Name ORDER BY LEN(Code))
    FROM dbo.Clothes
)
SELECT Name, Code
FROM cte
WHERE rn = 1;

SQLfiddle demo

如果您有多个共享相同长度的代码值,则选择将是任意的,因此您可以通过添加附加的order by子句来打破平局,例如:

OVER (PARTITION BY Name ORDER BY LEN(Code), CONVERT(INT, Code) DESC)

SQLfiddle demo

答案 1 :(得分:1)

试试这个

select clothes.name, MIN(code)
from clothes
    inner join
    (
        SELECT 
            Name, Min(Len(Code)) as CodeLen
        FROM
            clothes 
        GROUP BY
        Name
    ) results
on clothes.name = results.name
and LEN(clothes.code) = results.CodeLen
group by clothes.name

答案 2 :(得分:0)

听起来您正在尝试对“代码”字段的数值进行排序。如果是这样,正确的方法是首先将其转换为INT,并将其用于排序/分钟函数(在子查询中),然后在主查询子句中选择原始代码。