簡體   English   中英

MySQL數據庫設計建議-使用聯接

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM