[英]MySQL Database design advice - using joins
我正在建立一個類似AJAX的搜索頁面,該頁面允許客戶選擇一個數字過濾器以縮小搜索范圍。 例如,用戶選擇了“ iPhone 5”,並具有用於容量(32GB,64GB)和顏色(黑色,白色..)的其他過濾器。
用戶只能為每個類別選擇一個單選框(因此他們可以選擇32GB和黑色)。但是他們不能選擇(32GB,64GB和黑色,因為其中兩個屬於“容量”類別)。
我在sqlfiddle上添加了架構(請忽略以下事實:我已經刪除了它們在適當的應用程序中存在的主鍵,它們剛剛與其他字段/數據一起被刪除,以最小化sqlfiddle)
http://sqlfiddle.com/#!2/964425
任何人都可以建議創建查詢的最佳方法來執行以下操作:
Get all the prices for device_id '2939' (iPhone 5) which has the 'attributes' of '32GB' AND 'Black'
我目前有這個-但這僅在選擇單個屬性時有效:
// search for device with '64GB' & 'Black' attributes (this currently doesn't return any rows)
SELECT `prices`.*
FROM (`prices`)
LEFT JOIN `prices_attributes` ON `prices_attributes`.`price_id` = `prices`.`id`
WHERE `prices`.`device_id` = '2939'
AND `attribute_option_id` = '19'
AND `attribute_option_id` = '47';
// search for device with '64GB' attribute only (this currently DOES return a row)
SELECT `prices`.*
FROM (`prices`)
LEFT JOIN `prices_attributes` ON `prices_attributes`.`price_id` = `prices`.`id`
WHERE `prices`.`device_id` = '2939'
AND `attribute_option_id` = '19';
關於數據庫設計的任何建議也將不勝感激
注意:我正在考慮在“價格”表中添加一個新列,並對其序列化匹配的attribute_ids-但是這對優化沒有好處(例如,它會比當前方法慢)
我認為您應該將IN運算符用於attribute_option_id,並為查詢動態設置值; 另外,使用group_by時,每個價格只有一行,因此實際上您可以獲得所有價格。 除此之外,設計還可以。
在這里,我舉了一個例子:
SELECT `prices`.*
FROM (`prices`)
LEFT JOIN `prices_attributes` ON `prices_attributes`.`price_id` = `prices`.`id`
WHERE `prices`.`device_id` = '2939'
and `attribute_option_id` in ('19','47')
group by `prices`.`device_id`, `prices`.`price`;
在這里,您還可以在價格中添加order子句:
order by `prices`.`price` desc;
解決此問題的另一種方法是使用不同的價格,例如:
select distinct(prices.price)
from prices
where prices.device_id = 2939
and id in (select price_id from prices_attributes where attribute_option_id in (19,47));
針對devices_attributes_options表多次聯接,對於每個屬性,項必須具有一次
像這樣的東西:
SELECT *
FROM devices a
INNER JOIN prices b ON a.id = b.device_id
INNER JOIN prices_attributes c ON b.id = c.price_id
INNER JOIN devices_attributes_options d ON c.attribute_option_id = d.id AND d.attribute_value = '32GB'
INNER JOIN devices_attributes_options e ON c.attribute_option_id = e.id AND e.attribute_value = 'Black'
WHERE a.id = 2939
至於將序列化的詳細信息放入字段中,這是一個非常糟糕的主意,將來會再次吸引您!
由於attribute_option_id
是一個原子值,因此同一行不能有兩個不同的值。 因此,您的WHERE
子句無法匹配任何記錄:
SELECT `prices`.*
FROM (`prices`)
LEFT JOIN `prices_attributes` ON `prices_attributes`.`price_id` = `prices`.`id`
WHERE `prices`.`device_id` = '2939'
AND `attribute_option_id` = '19' # Here for one row, attribute_option_id is either 19
AND `attribute_option_id` = '47'; # of '47'. Cannot be the both
如果您覺得可讀性更高,可以嘗試使用子查詢來代替JOIN。 我認為MySQL允許該語法:
SELECT `prices`.*
FROM `prices`
WHERE `prices`.`device_id` = '2939'
AND EXISTS (SELECT *
FROM prices_attributes
WHERE price_id = `prices`.`id`
AND attribute_option_id IN ('19', '47') )
我不知道MySQL如何優化上述解決方案。 一種替代方法是:
SELECT `prices`.*
FROM `prices`
WHERE `prices`.`id` IN (
SELECT DISTINCT `price_id`
FROM prices_attributes
WHERE attribute_option_id IN ('19', '47')
)
SELECT * FROM prices WHERE device_id=2939 AND id IN (SELECT price_id FROM prices_attributes WHERE attribute_option_id IN (19,47));
你在找什么
編輯:對不起,沒有注意到您要使用聯接查詢
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.