1

私の質問を抽象的な言葉で説明することはできません。非常に単純な質問ですが、この非常に明白な例を確認する必要があります。それは完全に構成されているので、同様のアプリケーションに匹敵するはずです。

ユーザーに関する情報を含むテーブルがたくさんあります。すべてのテーブルは正規化されていると私が信じているものであり、一部の値はIDを介した他のテーブルへの参照にすぎません。

私はmySQL(およびmysqli拡張機能を備えたPHP-問題がある場合は疑わしい)を使用しています

だからここに例えば私が持っているものがあります:

table user_data

=====================================================
|| User_ID || Name || age || gender || location_ID ||
=====================================================
|| U000001 || Paul || 30  || m      || L00001      ||
|| U000002 || John || 20  || m      || L00001      ||
|| U000003 || Mike || 25  || m      || L00002      ||
|| U000004 || Anna || 25  || f      || L00003      ||


table user_personal_info

============================================
|| User_ID || color || food  || profession||
============================================
|| U000001 || red   || pizza || architect ||
|| U000002 || blue  || pasta || policeman ||
|| U000003 || green || steak || plumber   ||
|| U000004 || pink  || salad || teacher   ||


table locations

========================================================
|| location_ID || country || state      || city       ||
========================================================
|| L00001      || USA     || New York   || New York   ||
|| L00002      || USA     || New York   || Buffalo    ||
|| L00003      || USA     || California || Sacramento ||
|| L00004      || Canada  || Ontario    || Toronto    ||
|| L00005      || Canada  || Quebec     || Montreal   ||



table user_activities

=========================================
|| activity_ID  || user_ID || priority ||
=========================================
|| A0003        || U000001 || 5        ||
|| A0005        || U000001 || 4        ||
|| A0004        || U000002 || 2        ||
|| A0006        || U000002 || 1        ||
|| A0001        || U000003 || 3        ||
|| A0002        || U000004 || 4        ||
|| A0001        || U000004 || 1        ||
|| A0003        || U000004 || 5        ||

table activities

=================================
|| activity_ID  || description ||
=================================
|| A0001        || surfing     ||
|| A0002        || exercising  ||
|| A0003        || baseball    ||
|| A0004        || theater     ||
|| A0005        || dancing     ||
|| A0006        || reading     ||

了解しました。コンセプトはわかりますよね?

各エントリを表示するには、次のmySQLステートメントを作成してから、PHPなどで結果セットをループします。

SELECT * FROM user_data
JOIN user_personal_info USING (User_ID)

彼らの好きな活動が何であるかを表示するために、私もこれをしなければなりません:

SELECT * FROM user_activities 
WHERE user_ID = (current user_id)

もちろん、アクティビティIDが何を表し、ロケーションIDが何を表すかを追加のクエリで変換する必要があります...

(ちなみに、2つのクエリを実行するのではなく、すべてのユーザーとそれに関連付けられているすべてのフィールドを表示する方法について、より良い提案がありますか?)

次に、非常に特定のユーザーを見つけるための徹底的な検索機能を構築したいと思います。PHPを使用して結果をフィルタリングする方法は知っていますが、最初にデータベース全体をダウンロードする必要があり、数千人のユーザーがDBに入ると、おそらく非常に長い時間がかかります。

男性、女性、またはその両方で、食べ物や色が好きで、特定の場所(location_ID = L00001程度)のユーザーを見つける方法を知っています...年齢に関するルールを割り当てる方法を知っています(=、> 、<...)。LIKE%?%パラメーターについて知っています。

私の質問は:

特定の国または特定の州のすべてのユーザーを見つけるにはどうすればよいですか?
* mySQLに、location_IDがlocation_IDの配列からのユーザーと一致するユーザーのみを表示するように要求するにはどうすればよいですか?*

1つおよび/またはより具体的なアクティビティを持つすべてのユーザーを見つけるにはどうすればよいですか? アクティビティの配列が配列(ANDバージョン)の少なくともすべてのアクティビティと一致するユーザーのみを表示するようにmySQLに要求するにはどうすればよいですか? * mySQLに、アクティビティの配列に配列からのアクティビティの少なくとも1つ(ORバージョン)が含まれているユーザーのみを表示するように依頼するにはどうすればよいですか?*

そして今、本当に重要な質問は次のとおりです。

これらのステートメントを上記の通常のステートメントと組み合わせるにはどうすればよいですか? 意味:ニューヨーク州からサーフィンに興味があり、男性でピザが好きなすべてのユーザーを見つけるにはどうすればよいですか? または 、READING、DANCINGに興味があり、30歳以上で、GREENが好きな米国のすべてのユーザーをどのように見つけることができますか? または 、配管工と女性であるカリフォルニア州サクラメントのすべてのユーザーを見つけるにはどうすればよいですか?

などなど。例は明らかに無限です!

誰かが「このキーワードを調べてみるべきだ」と私に言うことができると確信しています。しかし、質問を簡潔に表現することができないため、多くの情報を見つけることができませんでした...

アップデート:

答えてくれてありがとう。私が指摘されたいくつかの有用なことがありました、これは私が知らなかったが今やっていることの要約です:

  • JOINをより効果的に活用する
  • IN演算子
  • HAVING COUNT()と組み合わせたGROUPBY演算子
  • およびサブ選択

それらを私に指摘してくれてありがとう!:)

4

1 に答える 1

1

さて、あなたが探しているキーワードの1つはIN演算子だと思います。

SELECT * FROM locations WHERE country IN ('USA', 'Canada', 'Denmark')

IN句の値の1つが国フィールドと一致するすべての行を返します。つまり、これを書くようなものです。

SELECT * FROM locations WHERE country = 'USA' OR country = 'Canada' OR country = 'Denmark'

残りの質問については:

2つのクエリを実行するのではなく、すべてのユーザーとそれに関連付けられているすべてのフィールドを表示する方法について、より良い提案がある人はいますか?

次のように、それらをすべて一緒に結合するだけです。

SELECT * FROM user_data
JOIN locations ON user_data.location_ID = locations.location_ID
JOIN user_personal_info ON user_data.User_ID = user_personal_info.User_ID
JOIN user_activities ON user_personal_info.User_ID = user_activities.User_ID
JOIN activities ON user_activities.activity_ID = activities.activity_ID

LEFT JOINもちろん、使用する構造やなどによって異なりますRIGHT JOIN。また、によってすべてのデータを取得するのは良い習慣ではありませんSELECT *が、実際には必要なフィールドのみを選択することをお勧めします。さらに、必要な結合データを表す1つ以上のビューを作成し、そこから選択することができます。

特定の国または特定の州のすべてのユーザーを見つけるにはどうすればよいですか?

SELECT user_data.* FROM user_data
JOIN locations ON user_data.location_ID = locations.location_ID
WHERE locations.country = 'USA' AND state = 'New York'

ユーザーからデータを取得する方法と、PHPでのステートメント用にデータを準備する方法によって異なります。たとえば、ユーザーが国を検索し、postメソッドを介してそれを取得するとします。

<?php
  $country = sanitize($_POST['country']);  // assuming a sanitation function for user input
  // whether by doing a sub-select
  $sql = "SELECT user_data.* FROM user_data WHERE user_data.location_ID = (SELECT locations.location_ID FROM locations WHERE locations.country LIKE '%{$country}%')";

  // or doing a join
  $sql = "SELECT user_data.* FROM user_data JOIN locations ON user_data.location_ID = locations.location_ID WHERE locations.country LIKE '%{$country}%'";
?>

もちろん、同じ原則が州にも当てはまります。

1つおよび/またはより具体的なアクティビティを持つすべてのユーザーを見つけるにはどうすればよいですか?

ここでは、アクティビティテーブルに対して結合し、上記のようにIN演算子を使用する必要があります。

これらのステートメントを上記の通常のステートメントと組み合わせるにはどうすればよいですか?

あなたの例をとると、サーフィンに興味があり、男性で、ピザが好きなニューヨーク州のすべてのユーザーをどのように見つけることができますか?

SELECT user_data.* FROM user_data
 JOIN locations ON user_data.locations_ID = locations.location_ID
 JOIN user_activities = user_data.User_ID = user_activities.user_ID
 JOIN activities ON user_activities.activity_ID = user_activities.activity_ID
WHERE locations.sate = 'New York'
  AND activities.description IN ('surfing')
  AND user_data.gender = 'm'
  AND user_personal_info.food = 'pizza'

これがあなたを正しい方向に導き、助けてくれることを願っています。

アップデート

もちろん、ここでのIN演算子はdescription = 'surfing'、値が1つしかないため、で置き換えることができます。description IN ('surfing', 'reading')そして、あなたがそれが意味するように別の値を追加するならば、あなたは正しいですsurfing OR reading。したがって、興味のあるすべてのユーザーを取得したい場合surfing AND readingは、副選択でそれを行うと思います。

SELECT user_data.* FROM user_data
 WHERE user_data.User_ID IN (
   SELECT user_activities.user_ID FROM user_activities
     JOIN activities ON user_activities.activity_ID = activities.activity_ID
    WHERE activities.description IN ('surfing', 'reading')
   GROUP BY user_activities.activity_ID
     HAVING COUNT(user_activities.user_ID) = 2
 )

したがって、副選択とは、「サーフィン」または「読み取り」で表示される各ユーザーIDをカウントし、カウントが2に等しい場合(両方に一致することを意味します)、ユーザーIDを取得することを意味します。そして、外側の選択は、サブセットのすべてのユーザーからデータを選択するだけです。

今、私はこれをテストしなかったので、それは変わるかもしれません。そして、おそらくもっと簡単な方法があります。このクエリを単純化するために少なくともできることは、前に述べたようにビューを作成し、そこから選択することです。

于 2013-01-14T01:42:28.840 に答える