2012-04-22 167 views
1

我做的是,我希望每個用戶都擁有自己的「獨特」編號系統。而不是自動遞增項目編號1,我做了這樣的事情,以便Bob的第一個項目從#1開始,而Alice的編號也將從#1開始。房間和類別也是如此。我通過爲項目,房間和類別創建「映射」表來實現這一目標。查詢6個表格,有沒有更好的方法來做到這一點?

下面的查詢工作,但我知道它絕對可以重構。我在每個表中都有主鍵(在「ids」上)。

SELECT unique_item_id as item_id, item_name, category_name, item_value, room_name 
       FROM 
        users_items, users_map_item, users_room, users_map_room, users_category, users_map_category 
       WHERE 
        users_items.id = users_map_item.map_item_id AND 
        item_location = users_map_room.unique_room_id AND 
        users_map_room.map_room_id = users_room.room_id AND 
        users_map_room.map_user_id = 1 AND 
        item_category = users_map_category.unique_category_id AND 
        users_map_category.map_category_id = users_category.category_id AND 
        users_category.user_id = users_map_category.map_user_id AND 
        users_map_category.map_user_id = 1 
       ORDER BY item_name 

users_items

| id | item_name | item_location |item_category | 
-------------------------------------------------------- 
| 1 | item_a |  1  |  1  | 
| 2 | item_b |  2  |  1  | 
| 3 | item_c |  1  |  1  | 

users_map_item

| map_item_id | map_user_id | unique_item_id | 
---------------------------------------------------- 
|  1  |  1  |   1  | 
|  2  |  1  |   2  | 
|  3  |  2  |   1  | 

users_rooms

| id | room_name | 
---------------------- 
| 1 | basement | 
| 2 | kitchen | 
| 3 | attic  | 

users_map_room

| map_room_id | map_user_id | unique_room_id | 
---------------------------------------------------- 
|  1  |  1  |   1  | 
|  2  |  1  |   2  | 
|  3  |  2  |   1  | 

users_category

| id | room_name | 
---------------------- 
| 1 | antiques | 
| 2 | appliance | 
| 3 | sporting goods | 

users_map_category

| map_room_id | map_user_id | unique_category_id | 
---------------------------------------------------- 
|  1  |  1  |   1  | 
|  2  |  1  |   2  | 
|  3  |  2  |   1  | 
+1

那麼您可以創建一個視圖並使用該視圖來使用該查詢。這會讓你有機會稍後改進它,而不需要改變使用它的任何地方(通過視圖)。這不是真正的解決方案,但希望有提示;) – Hajo 2012-04-22 16:23:35

+0

'item_value'在你的表中無處?如果在連接表中找不到匹配的行,請聲明您想要執行的操作。顯示「NULL」或從結果中刪除行? – 2012-04-22 16:41:05

+0

我忽略了包含所有我需要的字段,但項目信息來自users_items表。 – luckytaxi 2012-04-22 16:42:48

回答

1

與明確的JOIN條件重寫您的查詢使它更具可讀性(同時做相同)。

SELECT mi.unique_item_id AS item_id 
    , i.item_name 
    , c.category_name 
    , i.item_value 
    , r.room_name 
FROM users_map_item  mi 
JOIN users_items  i ON i.id = mi.map_item_id 
JOIN users_map_room  mr ON mr.unique_room_id = i.item_location 
JOIN users_room   r ON r.room_id = mr.map_room_id 
JOIN users_map_category mc ON mc.unique_category_id = i.item_category 
JOIN users_category  c ON (c.user_id, c.category_id) 
           = (mc.map_user_id, mc.map_category_id) 
WHERE mr.map_user_id = 1 
AND mc.map_user_id = 1 
ORDER BY i.item_name 

結果沒有變化。查詢計劃應該是一樣的。我看不出進一步改進查詢的方法。

如果您想保留結果中沒有找到匹配行的行,您應該使用LEFT [OUTER] JOIN而不是[INNER] JOIN。在這種情況下,您可能需要將其他WHERE條款移至JOIN條件,因爲它會更改結果。

+0

謝謝,爲什麼''users_category'與'users_room'不同? – luckytaxi 2012-04-22 17:09:38

+0

@luckytaxi:我使用這種語法形式一次匹配兩列。它與'ON c.user_id,= mc.map_user_id AND c.category_id = mc.map_category_id'同義,但更短且(IMO)更清晰。換行符只是爲了提高可讀性。 – 2012-04-22 18:16:32

+0

有意義,但是爲什麼有'ON c.user_id = mc.map_user_id'而不是一個用於房間映射表?無論哪種方式,查詢工作正常,但我只是好奇。謝謝 – luckytaxi 2012-04-22 19:00:20

相關問題