2011-12-09 48 views
2

我一直在努力嘗試弄清楚如何最有效地做到這一點。搜索我的年齡組的數據庫方案

問題如下。我有一個數據庫中的項目爲特定年齡羣體,如ages 10 to 20ages 16+在市場上銷售,我需要能夠進行查詢一樣,find item that is for 17 year old

這裏是我的兩個最好的想法(不過我也不喜歡,因爲我認爲它們都效率低下)。

  1. 有像10-2016+值的CSV列,檢索整個列表,並通過它解析(壞主意,我知道,我是新鮮的想法雖然這裏)

  2. 有無與像10,11,12,13...20值的CSV列範圍,這樣我就可以看它使用WHERE ages LIKE "%17%"了,並像16+案件我不得不檢索使用這些東西的特殊情況一樣WHERE ages LIKE "%+%"並通過這些分析。

我當然傾向於第二種方案,但在最好的情況下,我運行兩個查詢一個定期項目,一個對於像16+

有沒有更好的辦法?如果沒有,你認爲你可以讓我的模型更有效率嗎?謝謝。

+0

哪個數據庫?並且請從你的詞彙表中刪除「csv專欄」,那種事情幾乎不是一個好主意。 –

+0

我意識到這一點,但就像我說過的,我在這裏想出路。感謝您的幫助:D – vvMINOvv

+0

我希望您將DOB存儲在數據庫中,而不是年齡(可能將年齡作爲計算列)? –

回答

3

你可以這樣說:

  1. 添加lower_ageupper_age列到你的表,無論是整數允許空值。
  2. 如果lower_age爲NULL,那麼沒有下限。
  3. 如果upper_age爲NULL,則不存在上限。
  4. 結合COALESCE和BETWEEN查詢。

爲了澄清(4),你要說的事情是這樣的:

select * 
from your_table 
where $n between coalesce(lower_age, $n) and coalesce(upper_age, $n) 

其中$n就是你要找的年齡。使用之間包容性的限制,以coalesce(lower_age, $n)忽略$n如果lower_age不爲空,讓您$n >= $n(即自動真上界)如果lower_age爲NULL;同樣爲upper_age

如果事情僅適合11歲,那麼你的[lower_age,upper_age]閉區間將[11, 11],16 +將[16, NULL],六,下會[NULL, 6],每個人都將是[NULL, NULL],沒有人會[23, 11]或其他任何與lower_age > upper_age(或更可能的是,一個CHECK約束會導致hissy適合的無效數據)。

+0

我正在研究你的解決方案謝謝你的 – vvMINOvv

+0

美麗的解決方案@ muistooshort,簡單明瞭。感謝您的完整描述,它對我們有很大的幫助:D。我喜歡這樣! – vvMINOvv

0

成才這樣的:

 
SELECT * 
    FROM tablename 
WHERE 17 BETWEEN start_age AND end_age 
+0

你將如何處理「16+」或「5歲以下」的情況? –

+0

說什麼@muistooshort,感謝的:d – vvMINOvv

1

爲此,您可以通過多種方式。如果你存儲用戶的年齡(不管)在該行中。然後你可以查詢年齡和> 16或< 30或10-20之間。另一種選擇是將其存儲爲按位。有一個參考表,並存儲您的不同範圍,如果他們可以有多個,那麼你只需將兩個行值加在一起。

1 = 10 
2 = 16+ 
4 = 10-20 
8 = 20-30 
16 = 20+ 
32 = 30+ 
. 
. 
. 
. 

然後在存儲個人信息,你可以將列設置爲int或BIGINT把你的喜好,然後他們是屬於你的任何羣體可以通過例如數量確定此表:

Table of Users 
ID  Name  BitWise 
1  test   2 
2  something  6 (2+4) 
3  blah   24 (8+16) 

但是我認爲它可能是一個有點矯枉過正與按位,你可能是最好只儲存歲多項針對一個運行的查詢。這很可能是最有效的。

+0

有了您的解決方案,如果我要尋找的東西,是一個22歲,我必須檢索整個表,並通過每個選項解析,因爲例如22將下降低於16+,20-30,20+。 至少這就是我得到的,我得到這個錯誤?感謝您的幫助順便說一句。 – vvMINOvv

+1

如果您的rdbms支持位圖索引,則不必檢索整個表。您將在內存中使用位圖索引,並對它們使用按位操作。仍然是全面的表格掃描,但沒有硬盤損失。 – wallenborn

+1

@vvMINOvv wellenborn聲明,如果你的表被索引,並且你的RDBMS支持索引,那麼你實際上會有這個緩存,所以沒有hdd命中。但是,如果您需要知道該人屬於多個類別,則只能使用此功能。如果它總是隻有一個類別,那麼我會堅持將這個年齡存儲在行中,並對此進行查詢。 – CBRRacer

1

你有多種選擇(沒有雙關語意)。對於年齡建議,最簡單的方法是將存儲MIN_AGE和MAX_AGE和查詢這樣的:

select * from item where :age between min_age and max_age 

,你必須決定是否允許空值這些列(那麼你需要使用COALESCE()或NVL( )或數據庫提供的用於處理與空值的比較的任何函數),或者爲這些列設置邊界值,您可以確定:年齡總是在兩者之間。

或者,你可以使用M:N的表

create table item_ages (item_id int not null, age int not null, constraint item_ages_pk primary key (item_id, age) 

,並用明確的值填充:

item_id | age 
------------- 
     1 | 16 
     1 | 17 
     1 | 18 

等。這在使用範圍時更麻煩,但也更靈活,並且由於數據庫可以爲表建立索引並可能將該索引存儲在內存中,所以查詢應該很快。您只需在輸入新項目或特定項目的年齡範圍發生變化時觸摸此表格。

注意CBRRacer的回答也有類似的特性:既分享您準備可以很容易地索引的數據結構的想法,並回答該指數過濾器的問題。這是在電子商務應用程序中存儲市場營銷數據的常用方法。該範圍的最終目標是使用專用包來存儲用於該目的的倒排索引。但對於一個簡單的年齡推薦,當然是過分的。

+0

thank's @wallenborn我也會研究你的解決方案。乾杯。 – vvMINOvv

+1

我似乎無法停止學習! @瓦倫博恩感謝你的推理解釋,這非常有幫助。我覺得我會在這個項目的另一個表中使用這個m:n概念。非常感謝你的幫助:D – vvMINOvv

+0

@vvMINOvv:如果你想停止學習,你就錯了。 –

相關問題