2011-01-01 12 views
1

ここに私のテーブルです:SQL - 各レコードを返すのは一度だけ

tblBusiness 
BusinessID, BusinessName 

tblTags 
TagID, Tag 

tblBusinessTagLink 
BusinessID, TagID 

どれ事業は、それに適用される複数のタグを持つことができます。今すぐユーザーがフィルタリングされ、「Office Supplies」と「Technology」とタグ付けされたビジネスだけが見つかるようにします。

どのようなSQL文を使用しますか?ここで私が提示したものよりも、私のテーブルのデザインが優れていますか?あなたは、単純な使用することができます

答えて

2
SELECT 
    b.BusinessId, 
    b.BusinessName 
FROM 
    tblBusiness AS b 
    INNER JOIN tblBusinessTagLink AS l ON l.BusinessId = b.BusinessId 
    INNER JOIN tblTags   AS t ON t.TagId  = l.TagId 
WHERE 
    t.TagName IN ('Technology', 'Office Supplies') 
GROUP BY 
    b.BusinessId, 
    b.BusinessName 

これはカテゴリのいずれかのいずれかであるすべての事業を選択します。唯一の両方のカテゴリのものを選択するには、あなたは(メートルを表現するために3つのテーブルを:nの関係)を使用している

HAVING COUNT(*) = 2 

メソッドを追加することができ、このタスクを解決するための標準的な方法で、あなたはそれを維持することができます。

個人的には、テーブル名に「ハンガリー表記」を使用しないでください(複数の表が複数でない場合は特に「タグ」ではなく複数の表名を使用しません)。下記の最初のコメントに答える


:より大きなデータセットの場合

は、このクエリのパフォーマンスは、インデックスに依存しています。すべての主キーには自然にインデックスが必要です。 tblBusinessTagLinkには、両方のフィールドをカバーする合成索引と、複合索引で最初に表示されないフィールドの索引を追加する必要があります。

アイデアが悪いのは、フィールドの開始検索以外のLIKE条件でインデックスを使用できない(つまり、データセットの増加に伴ってパフォーマンスが急激に低下する)ためであり、部分的にはWHERE ','+keywords+',' LIKE '%,technology,%'または部分一致/偽陽性を取得します。

また、TagIdでクエリするのが少し効率的かもしれません。この方法は、あなたが完全に登録しようから一つのテーブルを削除することができます。

FROM 
    tblBusiness AS b 
    INNER JOIN tblBusinessTagLink AS l ON l.BusinessId = b.BusinessId 
WHERE 
    l.TagId IN (1, 2) 

あなたはしかしTagNameで照会する場合は、このフィールドにインデックスが同様に絶対に必要になります。

+0

ハンガリーの記法と複数の名前に関する注釈に感謝します。私はまだAccessデータベースを構築している間に学んだことをすべて取り消そうとしています。ビジネスエントリの数が増えるとこのクエリのパフォーマンスは低下しますか?または、選択されたタグの数が増加すると、または両方?私はユーザーに、5〜6個のタグが適用されているレコードを選択するオプションを提供する予定です。ときには、タグを取得してキーワードフィールドに格納する方が速いのではないかと思うことがあります。b.BusinessID、b.BusinessNameをtblBusinessから選択します。 '%technology%'のようなキーワードと... – HK1

+0

その他のコメントを見る私の答えで。 – Tomalak

0

は、レコード

SELECT t.Tag, b.BusinessName 
FROM tblBusiness b, tblTags t, tblBusinessTagLink l 
WHERE t.TagID = l.TagID 
AND l.BusinessID = b.BusinessID 
AND t.Tag = 'Office Supplies' 
+0

私はいくつかのことを理解していません。 "t"と "b"はあなたのテーブル名ですか?join文はどこにありますか?またはこのSQL文はjoinを必要としませんか?また、タグ「技術」は指定していません。 – HK1

+0

これらはエイリアステーブルの名前です – DKnight

+0

2つのカテゴリが選択され、私のクエリで結果が得られない場合、正しいレコードを返そうとしました。 tタグ= 'オフィスID'と[タグID] AND l.BusinessID = b]。[BusinessID])AND (t.Tag = 'Technology' AND t.TagID = [l]。[TagID] AND l.BusinessID = [b]。[BusinessID]); – HK1

-1

あなたは2つのクエリ(「事務用品」と「技術」のいずれかの1)をマージするINTERSECT集合演算を使用することができますを取得するために参加します。

ただし、INTERSECTをサポートしていないMySQLを使用している場合は、「HAVING COUNT(*)= 2」like thisのUNION ALLを使用できます。


EDIT:

また、すべてのように似UNIONせずに2番目のオプションを使用することができます。

select Name from tblBusiness 
left join tblBusinessTagLink on tblBusinessTagLink.BusinessID = tblBusiness.ID 
left join tblTags on tblTags.TagID = tblBusinessTagLink.TagID 
where Tag = 'Office Supplies' or Tag = 'Technology' 
group by name 
having count(Name) = 2; 
+0

私はあなたの解決策がTomalak'sと同じかどうかを調べようとしています。ユーザーが "OR"の代わりに "AND"を使用して一度に3つまたは4つのタグを適用したい場合は、どうすればよいでしょうか? – HK1

+0

私はTomalakと私のソリューションの両方が同じであると信じています。しかし、私はどこでx(y、z)とmy(x = yまたはx = z)の間でベンチマークをすることを強くお勧めします。また、1つのビジネスに同じタグが2回あると、正しく動作しないことにも注意してください。あなたのコメントのために – threenplusone

+0

ありがとう。ユーザーが同じタグを2回入力しないようにするための手順をとると思います。 – HK1

関連する問題