2011-12-09 19 views
2

これをしばらくの間苦労して、今これを最も効率的に行う方法を見つけようとしています。私の年齢グループを検索するためのデータベーススキーム

問題は次のとおりです。私は、データベース内のアイテムは、ages 10 to 20ages 16+などの特定の年齢層のために販売する必要があり、私のようなクエリを作成できるようにする必要があり、ここでfind item that is for 17 year old

は私の2つの最高のアイデアです(私はどちらか好きではありません、彼らは両方とも非効率だと思うので)。

  1. 10-2016+のような値を持つCSVファイルの列を持って、全体のリストを取得し、

  2. てきた(悪いアイデアは、私が知っている、私はここにかかわらず、アイデアの新鮮なうちだ)、それを解析範囲は10,11,12,13...20のような値を持つcsv列ですので、WHERE ages LIKE "%17%"を使用して調べることができます。16+のようなケースでは、WHERE ages LIKE "%+%"などの特殊なケースを取得して解析する必要があります。

私は2番目のオプションに傾いもちろんだけど、非常に最高のシナリオでは、私は定期的なアイテムのための2つのクエリのいずれかを実行しているよ、と16+

のようなもののための1つは、より良いあり方法?そうでなければ、私のモデルのどちらかをより効率的にすることができると思いますか?ありがとう。このような

+0

どのデータベースですか?そして、あなたの語彙から "csv column"を削除してください。そのようなことはほとんど決して良い考えではありません。 –

+0

私はこれを理解しますが、私が言ったように私はここでアイデアから脱出しています。 D – vvMINOvv

+0

年齢ではなくデータベースにDOBを格納することをお勧めします(おそらく計算列としての年齢を使用しています)。 –

答えて

3

あなたはこのようにそれを行うことができます。

  1. 、あなたのテーブルにNULLを許可する両方の整数をlower_ageupper_age列を追加します。
  2. lower_ageがNULLの場合、下限はありません。
  3. upper_ageがNULLの場合、上限はありません。
  4. クエリにCOALESCEとBETWEENを結合します。$nは、あなたが探している時代です

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

    :明確にするために

(4)、あなたはこのようなことを言いたいです。 BETWEENは包含的な境界を使用するので、lower_ageがNULLの場合は、(つまり、そのバインドでは自動的にtrue)を返します。は$nを無視します。 upper_ageの場合も同様です。

何かが唯一の11歳児に適している場合は、あなたの[lower_age,upper_age]閉じ間隔は[11, 11]なり、16+は[16, NULL]、6と低くなるが[NULL, 6]だろう、誰もが[NULL, NULL]だろう、と誰もが[23, 11]か何かないだろうlower_age > upper_age(またはCHECK制約がひどいフィットを捨てる無効なデータである可能性があります)。

+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つのオプションは、これをビット単位で格納することです。複数の値を持つことができる場合は、参照テーブルを用意し、異なる範囲を格納してから、2つの行の値を加算します。

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歳のものを検索すると、テーブル全体を取得して、それぞれのオプションを解析する必要があります。 16歳未満、20-30歳、20歳未満。 少なくともそれは私が得たものですが、これは間違っていますか?あなたの助けてくれてありがとうbtw。 – vvMINOvv

+1

rdbmsがビットマップ索引をサポートしている場合は、表全体を取り出す必要はありません。メモリ内にビットマップインデックスを持ち、ビットマップ演算を使用します。まだ完全なテーブルスキャンではありますが、ハードディスクのペナルティはありません。 – wallenborn

+1

@vvMINOvv wellenbornは、あなたのテーブルがインデックスされ、あなたのRDBMSがインデックスをサポートしているなら、あなたは実際にキャッシュされているので、hddヒットはないと言っています。しかし、あなたがその人物が複数のカテゴリに分類されることを知る必要がある場合にのみ、これを使用します。それが常に1つのカテゴリに過ぎない場合、私は行の年齢を格納してそれに照会することに固執します。 – CBRRacer

1

あなたにはさまざまなオプションがあります(意図しない)。年齢推奨事項については、最も簡単な方法は、このようなmin_ageとmax_ageのとクエリを保存することです:

あなたはこれらの列(そして、あなたはCOALESCEを(使用する必要があります)またはNVL(のためにNULLを許可するかどうかを決定する必要があり
select * from item where :age between min_age and max_age 

)、またはデータベースがnullとの比較を処理するために提供する関数)を使用するか、またはこれらの列の境界値を設定します。

また、あなたは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の回答には同様のプロパティがあります。どちらも、簡単に索引付けできるデータ構造を準備し、その索引からフィルタの質問に答えるという考えを共有しています。これは、eコマースアプリケーションにマーケティングデータを保存する一般的な方法です。その範囲の最終点は、その目的のために逆索引を格納する専用のパッケージを使用することです。しかし、単純な年齢の推薦のために、それは残酷なことです。

+0

ありがとうございます@wallenborn私はあなたのソリューションも研究しています。乾杯。 – vvMINOvv

+1

私はそれを学ぶのを止めることができない! @wallenbornはあなたの推理の説明に感謝し、それは信じられないほど役に立つものでした。私はこのプロジェクトで持っている別のテーブルでこのm:nの概念を使用するつもりです。あなたの助けを大変ありがとうございます:D – vvMINOvv

+0

@vvMINOvv:学習をやめたいなら間違った場所にいます:) –

関連する問題