我有以下数据库结构:
id idproperty idgbs
1 1 136
2 1 128
3 1 10
4 1 1
5 2 136
6 2 128
7 2 10
8 2 1
9 3 561
10 3 560
11 3 10
12 3 1
13 4 561
14 4 560
15 4 10
16 4 1
17 5 234
18 5 120
19 5 1
20 6 234
21 6 120
22 6 1
以下是详细信息:
该表引用idproperty
具有不同的地理位置。例如:
idgbs
1 refers to United States
10 refers to Alabama with parentid 1 (United States)
128 refers to Alabama Gulf Coast with parentid 10 (Alabama)
136 Dauphin Island with parentid 128 (Alabama Gulf Coast)
所以,结构是:
United States > Alabama > Alabama Gulf Coast > Dauphin Island
我想删除idproperty的所有条目除了第一个带有idgbs 136,128,10,1的集合,即在所有GBS中保留至少1个属性并删除其他属性。
此外,有时它是4级地理条目,有时它是3级。
请分享逻辑& SQL查询删除除每个唯一GBS中的条目之外的所有条目。
GBS 1,10,128,136是一个唯一的,因此数据库应该只包含1个带有这些GBS的属性ID。
查询后,表格如下所示:
id idproperty idgbs
1 1 136
2 1 128
3 1 10
4 1 1
9 3 561
10 3 560
11 3 10
12 3 1
17 5 234
18 5 120
19 5 1
改述这个问题:
我想在每个根级别GBS中保留属性,即在多芬岛应该只有一个属性。
答案 0 :(得分:3)
哇...我想我明白你现在的样子。我不能让这一个去; - )
我必须意识到,在这个问题中,你想要删除属性2,因为它与属性1共享一个层次结构。一旦我意识到这一点,我得到了以下想法。基本上,我们加入self的聚合版本两次:第一个告诉我们“gbs层次结构路径”是什么,第二个匹配任何之前的属性与相同层次结构。发现没有共享其层次结构的“先前”属性的行将被删除,其余的具有该层次结构将被删除。这可能会进一步调整,但我现在想分享这个。我已经使用您显示的数据对其进行了测试,并且我得到了您发布的结果。
DELETE
each_row.*
FROM property_gbs AS each_row
JOIN ( SELECT
idproperty,
GROUP_CONCAT(idgbs ORDER BY idgbs DESC SEPARATOR "/") AS idgbs_path
FROM property_gbs
GROUP BY idproperty
) AS mypath
USING(idproperty)
LEFT JOIN ( SELECT
idproperty,
GROUP_CONCAT(idgbs ORDER BY idgbs DESC SEPARATOR "/") AS idgbs_path
FROM property_gbs
GROUP BY idproperty
) AS previous_property
ON mypath.idgbs_path = previous_property.idgbs_path
AND previous_property.idproperty < each_row.idproperty
WHERE previous_property.idproperty
请注意,最后一行不是拼写错误,我们只是检查是否存在具有相同路径的先前属性。如果有,则删除当前评估的行。
干杯!
这里的想法是将每一行与它的层次结构相关联,即使它是一个代表层次结构中间某处的行(例如问题中的行:{2,1,128})。第一次加入聚合时,每一行现在“知道”它的路径是什么(因此该行将获得“136/128/10/1”)。然后,我们可以在第二个连接中使用该值来查找具有相同路径的其他属性,但前提是它们具有LOWER属性id。这允许我们检查是否存在具有相同“路径”的低ID属性,并删除代表具有这样的“低阶路径 - 兄弟”属性的任何行。
答案 1 :(得分:2)
我真的不确定。但试试这个。
DELETE a1 FROM table a1, table a2
WHERE a1.id > a2.id
AND a1.idgbs = a2.idgbs
AND a1.idgbs <> 1
如果你想让行保持最低的id。
答案 2 :(得分:2)
这个很难@dang,但我很享受这个挑战。
;With [CTE] as (Select id ,idproperty ,idgbs ,Row_Number() Over(Partition By idgbs order by idproperty Asc) as RN From [TableGBS])
,[CTE2] as (Select * From [CTE] Where RN > 1)
,[CTE3] as (Select idproperty ,count(*) as [Count] From [CTE2] Group by idproperty)
Delete from [TableGBS] Where id in (Select a.id From [CTE] as a Left Join [CTE3] as b on a.idproperty = b.idproperty Where RN > 1 And [Count] > 2);
因为我不认为你可以在sqlfiddle中执行删除语句,所以它将删除的行显示在select语句中:http://sqlfiddle.com/#!3/08108/40
编辑:我使用链接到Microsoft SQL Server Management Studio的MySQL,因此这可能不适合您
答案 3 :(得分:0)
这种技术将表与其自身的聚合版本连接起来,基本上将表中的每一行与idproperty最低的知识相匹配,如果它不共享该idproperty,则删除该行(即行具有最低idproperty,当连接到自身时,将不会被删除,但具有该idgbs的其余行将会被删除。
DELETE
each_row.*
FROM table AS each_row
JOIN (select MIN(idproperty), idgbs FROM table GROUP BY idgbs) as lowest_id
USING(idgbs)
WHERE each_row.idproperty != lowest_id.idproperty;