2016-09-03 16 views
2

複数のWHERE条件を必要とするSELECT文を作成しようとしています。それは可能ですか?ここにシナリオがあります。私は次の構造のテーブルを持っています。WHERE条件が複数あるSELECT文

フォームID(タイプのInt)
SubmissionID(タイプのInt)
フィールド名(タイプ テキスト)
たFieldValue(タイプテキスト)

データはこのようなものになるだろう。 表名:SubmissionsValue

FormID - SubmissionID - FieldName - FieldValue 
24 ------ 5 ---------- username ------ johnk 
24 ------ 5 ---------- firstname ------ John 
24 ------ 5 ---------- lastname ------ King 
24 ------ 5 ---------- address ------ 100 some street 
24 ------ 5 ---------- email ------ [email protected] 

24 ------ 9 ---------- username ------ cathym 
24 ------ 9 ---------- firstname ------ Catherine 
24 ------ 9 ---------- lastname ------ Mirusia 
24 ------ 9 ---------- address ------ 100 some other street 
24 ------ 9 ---------- email ------ [email protected] 

32 ------ 20 ---------- username ------ johnk 
32 ------ 20 ---------- firstname ------ John 
32 ------ 20 ---------- lastname ------ King 
32 ------ 20 ---------- address ------ 100 some street 
32 ------ 20 ---------- email ------ [email protected] 
32 ------ 20 ---------- AdultTicket------ 5 
32 ------ 20 ---------- SingleTicket------ 3 
32 ------ 20 ---------- Total ------ $60.00 

は、どうやらこれはエンティティ - 属性値(EAV)デザインで、私が言われています!

"FieldName"、 "FieldValue"などがわかるように、テーブルのフィールドの実際の名前です。また、同じユーザーの複数のフォームのエントリをテーブルに表示することもできます。だから私のキーフィールドは、ユーザーのemailIDと、フォームIDです。

フィールド名は、各オンラインフォームのfieldvalueとともにテーブルに格納されます。

"username"、 "firstname"、 "lastname"、 "address"、 "email"はフォームの実際のフィールドです。ユーザーが情報を送信すると、上記のようにテーブルに格納されます。

電子メールIDをキーフィールドとして使用して、別の領域にユーザーの詳細を表示したいとします。

は基本的にこの現象が発生しているものである(する$ user->は、電子メールは、現在のユーザーの電子メールを与える):

SELECT username WHERE (FieldName = "email") AND (FieldValue = " $user->email") 

しかし、値「johnk」を取得するための現実にして「cathym 「私の例では、どのような私が、次のされなければならないようですが、私はそれをコーディングする方法がわからないです:

SELECT FieldValue WHERE (FieldName = "username") 
     (WHERE (FieldName = "email") 
     AND (FieldValue = " $user->email")) 

誰かが、このスクリプトで私を助けてくださいことはできますか?

これはRSForm!Proを使用しているJoomlaサイト用です。 RSForm!Proはフォーム入力を上記の方法で保存します!!!

=== EDIT ====

明確化:上記に示しテーブルデータは、すべて一つのテーブルです。私は読みやすさのために2つのデータセットの間にスペースを追加しました。

FormIDとSubmissionIDは基本的に無視できます。バックエンドは、さまざまな異なるフォームのエントリをすべて1つのテーブルに保持するため、formIDとsubmissionIDを追跡します。最終的に、そのテーブルにはさまざまなformIDとsubmissionIDが存在することがわかります。

この例では、データは同じフォームから入力されましたが、2つの異なる提出物(5 & 8)が入力されました。これを解決するには、この場合には

、私は単純にログインしているユーザーの情報を新しいフォームのフィールドを自動入力します。

Last Name: John King 
User Address: 100 Some Street 
etc... 
+0

どのような電子メールIDですか?それは電子メールアドレスですか?あなたの質問を編集して、あなたの入力と希望する出力が何であるかを教えてください。間違った出力を見せているので、意図した結果が表示されます。 – Martin

+0

そして、FormIdでは何が起こっているのですか?それは誰にとっても同じであることを意図していますか? – Martin

+0

[こちらの回答](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php)では、SQLインジェクションを回避する方法について説明します。質問についての質問:FieldValueがユーザーの電子メールでFieldNameがユーザー名か電子メールのいずれかである場合、テーブルからユーザー名を選択しますか? – Terminus

答えて

1

一つの可能​​性は、サブクエリを使用することです。

SELECT t.FieldValue 
FROM table t 
WHERE t.FormID = (
    SELECT min(FormID) 
    FROM table 
    WHERE (FieldName = "email") 
    AND (FieldValue = "$user->email") 
) AND t.SubmissionID = (
    SELECT min(SubmissionID) 
    FROM table 
    WHERE (FieldName = "email") 
    AND (FieldValue = "$user->email") 
) AND t.FieldName ="username" 

もう1つの可能性は、テーブル自体に参加することです。

SELECT u.FieldValue 
FROM table u 
    JOIN table e ON u.FormID = e.FormID 
    AND u.submissionID = e.submissionID 
WHERE e.FieldName ="email" 
    AND e.FieldValue = "$user->email" 
    AND u.FieldName = "username" 

サブクエリ解は、MySQLがクエリを最適化するうえでどの程度うまくいくかによっては遅くなる可能性があります。

+0

haha​​、私の答えを盗む、nice ';-)' – Martin

+0

申し訳ありませんが、同時に複数の人が同じような答えを書くのは残念です。私たちも同じアイデアを持っていたようです。 – mm759

+0

私は自分の答えを掲示してあなたの答えを見て、あなたは自己結合表を言及していない、そして数分後に自己結合表を追加する答えを編集する。私の答えを見て自分の ':-p'にコピーしたかったようです。私は煩わされることはありませんが、あなたが私の答えを読んでいると思っていただけの場合は、謝辞の注釈は礼儀正しいと思います。とにかく、これらのコメントはそれを ':-)'と説明します。何の心配もなく – Martin

2

あなたは自己のテーブルを結合することができます。

SELECT t2.FieldValue FROM <table> t1 
     INNER JOIN <table> t2 ON t1.formId = t2.formId 
     WHERE t1.fieldName = 'email' 
     AND t1.fieldValue = '$user->email' 
     AND t2.fieldName = 'username' 

私ははこれがあなたの望ましい結果をもたらすだろうと思い、それは自己同じテーブルに参加しているので、あなたは正しい値を返すことが可能です。私は残念ながらこれを今はテストすることはできませんが、うまくいけば、これはあなたが何をしているかです。

は、基本的に、テーブルは、行のみのx数を返すことができ、そして行が返される行を参照することはできません(私の知る限り)ので、代わりにNULL値を参照すると、テーブルに設定されている自己結合(すべての関連する行の間の接続)のFormId欄のFormIdには、WHERE句でチェックされるデータは既にFormIdのすべての行になっています。

あなたはformIDを知らず、それを見つける方法がないので、これは現行のSQLでは不可能です(サブセレクトでも可能ですが、そのルートを楽しまなかった可能性があります)。

したがって、新しいSQLの最初の部分は、FormId = numberのブロック全体を返します。次に、このブロックで、email address = [email protected]のどこかをチェックし、対応するユーザー名を返します。

こちらがお役に立てば幸いです。


も準備文とどのようにコードのPHPとSQL正確に悪用さとリスクデータベースを離れることなく、を研究してください。 Please read this link投稿者:Terminus PHP The Right Wayまた、この件については非常に参考になります。

+0

は私の実際のテーブル名で置き換えられるはずですか? – rpacdn

+0

あなたの質問に答えたときにあなたのテーブル名を与えなかったので、そうです。 MySQLの構文を学ぶためにはうまくいくでしょう: ') – Martin

0

まず、フォームIDとSubmissionIdは、サブクエリで電子メールに対応する取得し、取得したフォームIDとSubmissionIdからユーザー名を取得

SELECT FieldValue FROM table t1, 
     (SELECT FormID, SubmissionID FROM table 
     WHERE FieldName='email' AND FieldValue = '$user->email') 
t2 WHERE t1.SubmissionID = t2.SubmissionID 
     AND t1.FormId = t2.FormID 
     AND t1.FieldName = 'username' 
+0

@Martinは、上記のコードのテーブルを実際のテーブル名に置き換えるものです。SubmissionValuesが私の実際のテーブル名である場合、上記のコードをどのように書くべきですか? t1とt2はテーブルハンドルだけですか? (申し訳ありませんが、私はSQLスクリプトで初心者です) – rpacdn

+0

ええ、実際のテーブル名で 'table'を置き換えるべきです。 t1とt2はエイリアスで、何でもかまいません – prasanth

1

データは、例えば

DROP TABLE IF EXISTS my_table; 

CREATE TABLE my_table 
(formID INT NOT NULL    -- Cannot be NULL 
,SubmissionID INT NOT NULL  -- Cannot be NULL 
,FieldName VARCHAR(20) NOT NULL -- Cannot be NULL 
,FieldValue VARCHAR(100) NOT NULL -- Could be NULL. Whether or not this can be NULL has important consequences for some of what follows!! 
,PRIMARY KEY(formid,submissionid,fieldname) 
); 

INSERT INTO my_table VALUES 
(24,5,'username', 'johnk'), 
(24,5,'firstname','John'), 
(24,5,'lastname', 'King'), 
(24,5,'address', '100 some street'), 
(24,5,'email', '[email protected]'), 
(24,9,'username', 'cathym'), 
(24,9,'firstname','Catherine'), 
(24,9,'lastname', 'Mirusia'), 
(24,9,'address', '100 some other street'), 
(24,9,'email','[email protected]'); 

を設定:

SELECT x.formid 
    , x.submissionid 
    , MAX(CASE WHEN fieldname = 'username' THEN fieldvalue END) username 
    , MAX(CASE WHEN fieldname = 'firstname' THEN fieldvalue END) firstname 
    , MAX(CASE WHEN fieldname = 'lastname' THEN fieldvalue END) lastname 
    , MAX(CASE WHEN fieldname = 'address' THEN fieldvalue END) address 
    , MAX(CASE WHEN fieldname = 'email' THEN fieldvalue END) email 
    FROM my_table x 
GROUP 
    BY formid 
    , submissionid 
HAVING email = '[email protected]'; 

+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 
| formid | submissionid | username | firstname | lastname | address   | email    | 
+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 
|  24 |   5 | johnk | John  | King  | 100 some street | [email protected] | 
+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 

または

SELECT x.formid 
    , x.submissionid 
    , x.fieldvalue email 
    , MAX(CASE WHEN y.fieldname = 'username' THEN y.fieldvalue END) username 
    , MAX(CASE WHEN y.fieldname = 'firstname' THEN y.fieldvalue END) firstname 
    , MAX(CASE WHEN y.fieldname = 'lastname' THEN y.fieldvalue END) lastname 
    , MAX(CASE WHEN y.fieldname = 'address' THEN y.fieldvalue END) address 
    FROM my_table x 
    JOIN my_table y 
    ON y.formid = x.formid 
    AND y.submissionid = x.submissionid 
    AND y.fieldname <> x.fieldname 
WHERE x.fieldname= 'email' 
    AND x.fieldvalue = '[email protected]' 
GROUP 
    BY formid 
    , submissionid 
    , email; 

+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 
| formid | submissionid | username | firstname | lastname | address   | email    | 
+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 
|  24 |   5 | johnk | John  | King  | 100 some street | [email protected] | 
+--------+--------------+----------+-----------+----------+-----------------+-------------------+ 

または

SELECT email.formid 
    , email.submissionid 
    , email.fieldvalue email 
    , username.fieldvalue username 
    , firstname.fieldvalue firstname 
    , lastname.fieldvalue lastname 
    , address.fieldvalue address 
    FROM my_table email 
    LEFT 
    JOIN my_table username 
    ON username.formid = email.formid 
    AND username.submissionid = email.submissionid 
    AND username.fieldname = 'username' 
    LEFT 
    JOIN my_table firstname 
    ON firstname.formid = email.formid 
    AND firstname.submissionid = email.submissionid 
    AND firstname.fieldname = 'firstname' 
    LEFT 
    JOIN my_table lastname 
    ON lastname.formid = email.formid 
    AND lastname.submissionid = email.submissionid 
    AND lastname.fieldname = 'lastname' 
    LEFT 
    JOIN my_table address 
    ON address.formid = email.formid 
    AND address.submissionid = email.submissionid 
    AND address.fieldname = 'address' 
WHERE email.fieldname = 'email' 
    AND email.fieldvalue = '[email protected]'; 

+--------+--------------+-------------------+----------+-----------+----------+-----------------+ 
| formid | submissionid | email    | username | firstname | lastname | address   | 
+--------+--------------+-------------------+----------+-----------+----------+-----------------+ 
|  24 |   5 | [email protected] | johnk | John  | King  | 100 some street | 
+--------+--------------+-------------------+----------+-----------+----------+-----------------+ 

EDIT:

あなただけの可能性が与えられたユーザーの提出に関連したすべての 'フィールド' を、返すようにしたい場合ただし、一般的なユーザーデータは通常は専用のテーブル内に保持されることに注意してください。 Joomlaのようなランプ:

SELECT a.* 
    FROM my_table a 
    JOIN my_table b 
    ON b.formid = a.formid 
    AND b.submissionid = a.submissionid 
WHERE b.fieldname = 'email' 
    AND b.fieldvalue = '[email protected]'; 
+--------+--------------+-----------+-------------------+ 
| formID | SubmissionID | FieldName | FieldValue  | 
+--------+--------------+-----------+-------------------+ 
|  24 |   5 | address | 100 some street | 
|  24 |   5 | email  | [email protected] | 
|  24 |   5 | firstname | John    | 
|  24 |   5 | lastname | King    | 
|  24 |   5 | username | johnk    | 
+--------+--------------+-----------+-------------------+