在 MS SQL Server 2008 中排除 "some" 重复行

Excluding "some" duplicate rows in MS SQL Server 2008

-- 有什么关于让它在 MS SQL Server 2008 中工作的建议吗?

-- 我对 'duplicate row' 的定义是“前 3 个字段匹配” -- 我需要从我的结果中排除重复项,但我决定保留哪 1 行 -- 保留第 4 列有值的行(每组重复对只有 1 行)

-- 结果将保留第 2 行(而不是第 1 行) -- 同时保留第 3 行(但不保留第 4 行) -- 同时保留所有剩余的行(none 是重复的) -- 应返回 10 行中的 8 行

IF(OBJECT_ID('tempdb..#tmp') IS NOT NULL)       DROP TABLE #tmp

CREATE TABLE #tmp
(
    aKey Int            IDENTITY(1,1)   PRIMARY KEY,    
    
    f1 VarChar(10)          NOT NULL    DEFAULT 0,  -- 1
    f2 VarChar(10)          NOT NULL    DEFAULT 0,  -- 2
    f3 VarChar(10)          NOT NULL    DEFAULT 0,  -- 3 
    f4 VarChar(10)          NOT NULL    DEFAULT 0,
    f5 VarChar(10)          NOT NULL    DEFAULT 0,
    f6 VarChar(10)          NOT NULL    DEFAULT 0
)

INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('A', 'B', 'C', '' , 'del', '1') -- 1st of the duplicate
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('A', 'B', 'C', 'D', 'keep', '1') -- 2nd of the duplicate

INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('D', 'E', 'F', 'G', 'keep', '2') -- 1st of the duplicate
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('D', 'E', 'F', '' , 'del', '2') -- 2nd of the duplicate

INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('H', 'G', 'N', 'Q', '1', 'K')  
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('I', 'G', 'C', '' , '2', 'L')  
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('J', 'H', 'D', 'R', '3', 'P')  
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('K', 'G', 'C', '' , '4', 'K')  
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('L', 'G', 'C', 'S', '5', 'V')  
INSERT INTO #tmp(f1, f2, f3, f4, f5, f6)    VALUES('K', 'M', 'C', '' , '6', 'K')  

--SELECT * 来自#tmp

-- This "almost" works, but is excluding too many non-duplicate rows:

SELECT DISTINCT t1.* FROM #tmp AS t1
INNER JOIN #tmp AS t2
ON t1.f1 = t2.f1 AND t1.f2 = t2.f2 AND t1.f3 = t2.f3
WHERE t1.f4 <> ''

首先,优秀的职位发布示例数据采用人们可以使用的格式。太棒了!!!!这使得人们很容易提供帮助。其次,即使您陈述的解释并不完全清楚,您确实在示例数据中提供了足够的详细信息以明确您需要完成的工作。 xQbert 指出使用 ROW_NUMBER 是解决此问题的好方法。

我在这里使用了 cte 来阐明其工作原理。如果需要,您可以像子查询一样轻松地做到这一点。

with SortedValues as
(
    select *
        , RowNum = ROW_NUMBER() over (partition by f1, f2, f3 order by f4 desc)
    from #tmp
)

select *
from SortedValues
where RowNum = 1
order by aKey

为了与您现有的方法保持一致,不要加入,只需使用 exists

select * 
from t
where not exists (
    select * from t t2 
    where t.f1=t2.f1 
        and t.f2=t2.f2 
        and t.f3=t2.f3 
        and t.f4 =''
        and t2.akey !=t.akey
    )