2017-07-04 9 views
4

私は、次の構造を有する:MySQLが垂直テーブルと水平参加

CREATE TABLE person { 
    id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
    name VARCHAR(30) NOT NULL, 
    email VARCHAR(30) NOT NULL UNIQUE 
} 

CREATE TABLE field { 
    id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
    name VARCHAR(30) NOT NULL 
} 

CREATE TABLE fieldPerson { 
    id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
    fieldId INT(11) UNSIGNED, 
    personId INT(11) UNSIGNED, 
    value VARCHAR(30) NOT NULL, 
    FOREIGN KEY (fieldId) REFERENCES field(id), 
    FOREIGN KEY (personId) REFERENCES person(id) 
} 

これがうまくまとめています。基本的にはデフォルトのフィールドnameemailがあり、telephoneaddressなどのカスタムフィールドを作成するオプションがあります。 nのフィールドがあります。私はSELECTクエリを行う方法を見つけようとしていますが、サブクエリやデータベース外の余分な作業を使わずにすべてのフィールドを返すようにしています。

例(電話はカスタムフィールドです):

TABLE person: 

id name  email 
1  Test 1  [email protected] 

---- 

TABLE field: 

id name 
1  telephone 
2  address 

---- 

TABLE fieldPerson: 

id fieldId personId value 
1  1   1   +1 555 555 555 
2  2   1   First St. 

---- 

RESULTING QUERY 

personId name   email   telephone  Address 
1   Test 1  [email protected] +1 555 555 555 First St. 

が可能ということですか?

ありがとうございました。

EDIT:

ことができない場合は、あなたがが唯一のSQLで、サブクエリを使用して最適なソリューションを提案することができます。

+0

しかし、私はJOINは避けられないと思います。 –

+0

もちろん、JOINは大丈夫です。サブクエリ '(SELECT ...)AS ... 'に頼りにしたくないだけです。 –

+0

いいえ、フィールドには名前列しかありません。私はそれの価値を集めて列名として使う必要があります。 –

答えて

2
SELECT p.* 
    , group_concat(CASE f.name WHEN 'telephone' THEN fp.value END) telephone 
    , group_concat(CASE f.name WHEN 'address' THEN fp.value END) address 
    FROM person p 
    JOIN field f 
    LEFT JOIN fieldPerson fp 
     ON fp.personId = p.id 
     AND fp.fieldId = f.id 
    GROUP BY p.id 
3

SELECT列をPRIMARY KEYと同じ順序で生成できる場合は、クエリ生成の制御量に応じて、fieldという列を生成することができます。私はfieldに2つのキーがあることを知っているところを想像しています。

SELECT fp.personId,p.name,p.email,fp.value as telephone,fp2.value as Address 
    FROM fieldPerson fp INNER JOIN person p ON p.id = fp.personId 
         INNER JOIN field f ON f.id = fp.fieldId 
         INNER JOIN fieldPerson fp2 
    WHERE fp.fieldId = 1 and fp2.fieldId = 2; 

これが問題のサンプルデータを考えると、私に結果を与える:

personId | name | email   | telephone  | Address | 
     1 | Test 1 | te[email protected] | +1 555 555 555 | First St. | 

これは、あなたが知っている、以前の初期のクエリを実行して、サブクエリを避けてきた概念にかかっfieldsテーブルに定義されている任意のフィールド。この表がどの程度動的であるかを指定しなかったので、これは不合理な単純化の仮定ではないかもしれません。

ことがなければ、あなたのような何かを試すことができます。

SELECT fp.personId,p.name,p.email,fp.value as telephone,fp2.value as Address 
    FROM fieldPerson fp INNER JOIN person p ON p.id = fp.personId 
         INNER JOIN field f ON f.id = fp.fieldId 
         INNER JOIN fieldPerson fp2 
    WHERE fp.fieldId != fp2.fieldId LIMIT 1,1; 

これは、フィールドのID番号を知らなくても私に同じ出力が得られますが、私は列を生成するフィールドの名前を知っておく必要があります名前。 LIMITは、JOIN製品の1つを削除するためにそこにあり、それには明らかに不快感を持っています、私は同意します。とにかく列名を知っておく必要があるので、2に近づくのはあまり利点がないように感じます。

@Mojtabaと同意しますが、動的なフィールド名とIDを知るための事前クエリを使用できない場合は、SELECT文を次のように入力する必要があります。クエリ時にそれらを引き出すことができます。

関連する問題