2013-01-15 34 views
3

我有兩個表如何重新鍵入表中的層次結構?

汽車:包含有關汽車

+-----+-------------+-----------+ 
| id | description | parent_id | 
+-----+-------------+-----------+ 
| 1 | All cars |   1 | 
| 30 | Toyota  |   1 | 
| 34 | Yaris  |  30 | 
| 65 | Yaris  |  30 | 
| 87 | Avensis  |  30 | 
| 45 | Avensis  |  30 | 
| 143 | Skoda  |   1 | 
| 199 | Octavia  |  143 | 
| 12 | Yeti  |  143 | 
+-----+-------------+-----------+ 

car_mapping層級數據:包含其中重複的車(有不同的ID)映射到一個ID映射數據。

+--------+----------+--------+ 
| car_id | car_name | map_id | 
+--------+----------+--------+ 
|  34 | Yaris |  1 | 
|  65 | Yaris |  1 | 
|  87 | Avensis |  2 | 
|  45 | Avensis |  2 | 
| 199 | Octavia |  3 | 
|  12 | Yeti  |  4 | 
|  30 | Toyota |  5 | 
| 143 | Skoda |  6 | 
|  1 | All cars |  0 | 
+--------+----------+--------+ 

現在,這個想法是創建一個第三個表,cars_new,基於汽車car_mapping從而消除重複和重新鍵層次的車基礎上,map_id表字段在car_mapping表中。這裏是導致cars_new

+--------+----------+---------------+ 
| map_id | car_name | parent_map_id | 
+--------+----------+---------------+ 
|  0 | All  |    0 | 
|  1 | Yaris |    5 | 
|  2 | Avensis |    5 | 
|  3 | Octavia |    6 | 
|  4 | Yeti  |    6 | 
|  5 | Toyota |    0 | 
|  6 | Skoda |    0 | 
+--------+----------+---------------+ 

這裏是SQL Fiddle這個問題。任何想法如何重新鍵入這個hiearchy?

+2

+1好問題,示例數據和示例代碼! –

回答

1
select distinct cm.map_id, cm.car_name, cm2.map_id parent_map_id 
from cars c, car_mapping cm, car_mapping cm2 
where c.id = cm.car_id 
and c.parent_id = cm2.car_id(+) 
order by cm.map_id; 

PS:在你的car_mapping表,你需要一個額外的行(下面第一個),以獲得準確的結果你想要的:

+--------+----------+--------+ 
| car_id | car_name | map_id | 
+--------+----------+--------+ 
|  1 | All  |  0 | 
|  34 | Yaris |  1 | 
|  65 | Yaris |  1 | 
Etc.. 
+0

謝謝,我添加了這一行。這是什麼cm2.car_id(+)? – jrara

+0

在我添加行之前,car_id = 1沒有匹配的map_id。因此,'(+)'(oracle中的外連接)告訴oracle獲取該行,即使car_mapping中沒有匹配條件'和c的行。 parent_id = cm2.car_id(+)'。現在這一行,沒有必要這樣做。 –

+0

非常整齊,謝謝! – jrara

1

基於@Majid LAISSI的接受的答案,這似乎在Oracle和SQL Server中都可以工作:

select distinct cm.map_id, cm.car_name, cm2.map_id as parent_map_id 
from cars c 
left outer join car_mapping cm on c.id = cm.car_id 
left outer join car_mapping cm2 on c.parent_id = cm2.car_id 
order by cm.map_id; 
1

您沒有層次結構,最好不要創建一個層次結構。注意你的「汽車」表沒有描述汽車;它只是給一個數字分配一個字符串(和另一個數字給這個數字)。從一開始,「所有汽車」不是一輛汽車,而「豐田」是一家汽車製造商,而不是汽車。

的解決方案 - 這將幫助你的獨特性的問題,並簡化您的疑問 - 是使用一個表中的每個不同的事情:

  • 生產{mfg_id,名} - 例如GM,Ford
  • make {make_id,name,mfg_id} - 例如雪佛蘭,林肯;製造商鏈接
  • models {name,make_id} - 例如雅力士等;鏈接。

請務必在「名稱」唯一在每個表中,以防止虛假的ID被創建。

這會讓您在出現這些事情時爲它們指定新的屬性,例如它們的製造年份或銷售數量,或每個型號進入多少個門。它還可以讓您防止福特對通用汽車或者說,讓Yaris成爲「所有汽車」的母公司。我建議你在表名中避開「映射」或「映射」,因爲它沒有說任何事情,每個表都將行中的元素相互關聯,每個表都將關鍵字映射到其表中好消息是你的car_mapping表在新設計中消失了。)

至於如何轉換現有的汽車表,這將是一個滋擾。 假設 cars_mapping是正確的,您可以插入到每個表中,加入並按名稱分組並取最小值(id)。你需要三個這樣的查詢,然後仔細觀察,以檢查,呃,不對齊。