2011-09-27 154 views
2

我有这样一个表:如何根据阈值删除除一些记录以外的所有记录?

CREATE TABLE #TEMP(id int, name varchar(100)) 

INSERT INTO #TEMP VALUES(1, 'John') 
INSERT INTO #TEMP VALUES(1, 'Adam') 
INSERT INTO #TEMP VALUES(1, 'Robert') 
INSERT INTO #TEMP VALUES(1, 'Copper') 
INSERT INTO #TEMP VALUES(1, 'Jumbo') 
INSERT INTO #TEMP VALUES(2, 'Jill') 
INSERT INTO #TEMP VALUES(2, 'Rocky') 
INSERT INTO #TEMP VALUES(2, 'Jack') 
INSERT INTO #TEMP VALUES(2, 'Lisa') 
INSERT INTO #TEMP VALUES(3, 'Amy') 

SELECT * 
FROM #TEMP 


DROP TABLE #TEMP 

我想删除所有,但一些记录对于那些有超过3名具有相同的ID。因此,我试图得到这样的东西:

id name 
1 Adam 
1 Copper 
1 John 
2 Jill 
2 Jack 
2 Lisa 
3 Amy 

我不理解如何编写此查询。我已经得到了为维护一个记录的程度,但不是记录的门槛:

;WITH FILTER AS 
(
    SELECT id 
    FROM #TEMP 
    GROUP BY id 
    HAVING COUNT(id) >=3 
) 
SELECT id, MAX(name) 
FROM #TEMP 
WHERE id IN (SELECT * FROM FILTER) 
GROUP BY id 
UNION 
SELECT id, name 
FROM #TEMP 
WHERE id NOT IN (SELECT * FROM FILTER) 

给我:

1 Robert 
2 Rocky 
3 Amy 

有什么建议?顺便说一句,我不在乎合并时保留了哪些记录。

+0

+1所提供的测试脚本。很容易理解和回答这些问题。 –

回答

2

可以使用CTE

做到落实DELETE语句查询
CREATE TABLE #TEMP(id int, name varchar(100)) 
INSERT INTO #TEMP VALUES(1, 'John') 
INSERT INTO #TEMP VALUES(1, 'Adam') 
INSERT INTO #TEMP VALUES(1, 'Robert') 
INSERT INTO #TEMP VALUES(1, 'Copper') 
INSERT INTO #TEMP VALUES(1, 'Jumbo') 
INSERT INTO #TEMP VALUES(2, 'Jill') 
INSERT INTO #TEMP VALUES(2, 'Rocky') 
INSERT INTO #TEMP VALUES(2, 'Jack') 
INSERT INTO #TEMP VALUES(2, 'Lisa') 
INSERT INTO #TEMP VALUES(3, 'Amy') 

SELECT * 
FROM #TEMP; 

WITH CTE(N) AS 
(
SELECT ROW_NUMBER() OVER(PARTITION BY id ORDER BY id) 
FROM #Temp 
) 
DELETE CTE WHERE N>3; 

SELECT * 
FROM #TEMP; 

DROP TABLE #TEMP 
+0

+1漂亮!完美的作品。被接受为答案,但请您添加一些解释? – Legend

+0

这很让人困惑,Legend想从输出行中删除额外的行或者从表中删除:-) ..良好的逻辑 –

+0

@Legend我在MSDN上添加了链接。 –

1

我会改变你的选择是这样的(未测试)

select name from #temp group by name having count(id) > 3 

那么你可以使用你选择的where子句

0
在内部查询

可以使用row_number功能上(由ID分区) ,然后在外部查询哟u必须给条件类似下面

select id,name from (
SELECT id,name, row_number() over (partition by id order by 1) count_id FROM #test 
group by id, name) 
where count_id <=3 
+0

你真的用OP测试数据来试试这个吗?它不工作! – Jamiec

+0

我测试了它..在我的机器上它正在工作.. –

+0

在SQL Server 2008上,由于需要为表格别名,因此''附近的位置'语法错误'。当你通过别名解决这个问题时,你会得到'窗口函数不支持整数索引作为ORDER BY子句表达式.'当你将'order by 1'更改为'order by id'时,它将*作用。很差的答案海事组织。 – Jamiec

0

如果我收到了你的问题的权利,你需要得到行时id发生3次或更多次

select t1.name,t1.id from tbl1 t1 
inner join tbl1 t2 on t1.id = t2.id 
group by t1.name, t1.id 
having count(t1.id) > 2 
+0

您是否真的使用OP测试数据来尝试此操作?它不工作! – Jamiec

+0

@Jamiec:是的,它在这里有效,与OP –

+0

的值相同当我测试你的答案时,它给出了所有的两个,而不是三个。 – Jamiec