0

私はこの性質のすべての質問がこのように始まると信じています... 私は2つのテーブルを持っています:fieldsdataFields(存在しない)テーブルの列名を記述し、その(存在しない)テーブルdataのデータを含みます。そのようです...

田畑:

    +----+---------+-------------+---------------+-------+----------+
    | ID | F_ORDER | NAME        | LABEL         | VALUE | TYPE     |
    +----+---------+-------------+---------------+-------+----------+
    |  1 |       1 | IS_EMPLOYEE | Region        |       | checkbox |
    |  2 |       3 | EM_AVATAR   | Avatar        |       | avatar   |
    |  3 |       4 | EM_JOBTITLE | Job Title     |       | text     |
    |  4 |       5 | EM_COMPANY  | Company       |       | text     |
    |  5 |       6 | EM_PHONE    | Phone         |       | text     |
    |  6 |       2 | EM_ORDER    | Display Order | 5     | text     |
    +----+---------+-------------+---------------+-------+----------+

データ:

    +-----+----------+---------+--------------------------------------+
    | ID  | FIELD_ID | USER_ID | VALUE                                |
    +-----+----------+---------+--------------------------------------+
    |   5 |        1 |       1 | YES                                  |
    |   6 |        2 |       1 |                                      |
    |   7 |        3 |       1 | Owner                                |
    |   8 |        4 |       1 | Acme, Inc.                           |
    |   9 |        5 |       1 | 123-456-7987                         |
    | 150 |        5 |      31 | 123-623-5555                         |
    | 149 |        4 |      31 | Acme, Inc.                           |
    | 148 |        3 |      31 | Sales and Customer Support           |
    | 147 |        2 |      31 |                                      |
    | 146 |        1 |      31 | YES                                  |
    |  26 |        1 |       6 | NO                                   |
    |  27 |        2 |       6 | http://example.com/avi/avi.jpeg      |
    |  28 |        3 |       6 | CEO                                  |
    |  29 |        4 |       6 | Acme                                 |
    |  30 |        5 |       6 | (123) 734-5555                       |
    |  31 |        1 |       7 | NO                                   |
    |  32 |        2 |       7 | http://example.com/avi/avi.jpeg      |
    |  33 |        3 |       7 | VP, Services                         |
    |  34 |        4 |       7 | Acme                                 |
    |  35 |        5 |       7 | (913) 963-5555                       |
    |  36 |        1 |      14 | NO                                   |
    |  37 |        2 |      14 | http://example.com/avi/avi.jpeg      |
    |  38 |        3 |      14 | Senior Accountant                    |
    |  39 |        4 |      14 | Acme                                 |
    |  40 |        5 |      14 | (123) 213-5555                       |
    |  41 |        1 |      10 | NO                                   |
    |  42 |        2 |      10 | http://example.com/avi/avi.jpeg      |
    |  43 |        3 |      10 | President                            |
    |  44 |        4 |      10 | Acme                                 |
    |  45 |        5 |      10 | (123) 734-5555                       |
    |  46 |        1 |      12 | NO                                   |
    |  47 |        2 |      12 | http://example.com/avi/avi.jpeg      |
    |  48 |        3 |      12 | Services Supervisor                  |
    |  49 |        4 |      12 | Acme                                 |
    |  50 |        5 |      12 | (123) 573-5555                       |
    |  51 |        1 |      11 | NO                                   |
    |  52 |        2 |      11 | http://example.com/avi/avi.jpeg      |
    |  53 |        3 |      11 | Operations Supervisor                |
    |  54 |        4 |      11 | Acme                                 |
    |  55 |        5 |      11 | (123) 259-5555                       |
    |  56 |        1 |       8 | NO                                   |
    |  57 |        2 |       8 | http://example.com/avi/avi.jpeg      |
    |  58 |        3 |       8 | General Information                  |
    |  59 |        4 |       8 | Acme                                 |
    |  60 |        5 |       8 | (123) 213-5555                       |
    |  61 |        1 |       9 | NO                                   |
    |  62 |        2 |       9 | http://example.com/avi/avi.jpeg      |
    |  63 |        3 |       9 | VP, Sales                            |
    |  64 |        4 |       9 | Acme                                 |
    |  65 |        5 |       9 | (123) 210-5555                       |
    +-----+----------+---------+--------------------------------------+

私が探しているクエリの基本的な言い回しは次のとおりです。従業員(IS_EMPLOYEE = "YES")であり、表示順序列(EM_ORDER)で並べ替えられたすべての人のすべての情報が必要です。

これまでの私の質問は私をどこにも導きません。次のような結果が得られます。

    +--------+------------+------------+-------+---------+-------+
     ID        FIELD_ID    NAME         LABEL   TYPE       VALUE
    +--------+------------+------------+-------+---------+-------+
     7         1           IS_EMPLOYEE  Region  checkbox   YES
    +--------+------------+------------+-------+---------+-------+

私が必要としているのは、次のような結果です。

    +-------+------------+---------+-----------+----------+-------------+--------+
     USER_ID IS_EMPLOYEE  EM_AVATAR EM_JOBTITLE EM_COMPANY EM_PHONE      EM_ORDER   
    +-------+------------+---------+-----------+----------+-------------+--------+
     6       YES           http://  CEO         Acme       123-123-555   5 
    +-------+------------+---------+-----------+----------+-------------+--------+ 

$results['user_id']['jobtitle']そしてもちろん、私はそれをすべて使用可能な配列(など)としてPHPに戻そうとしています。すべてを取得してPHPで処理することもできますが、MySQLを学習しようとしています。これは、いくつかのforeachブロックを実行するよりも高速な方法だと思います...間違っている可能性はありますが。

助けてくれてありがとう。

4

2 に答える 2

3

データテーブルはEntity-Attribute-Value方式で編成されていますが、これはリレーショナルデータを格納する有効な方法ではありません。SQLを使用して、属性ごとに1つの列を持つ従来の行に取得するのが面倒なのも不思議ではありません。

SQLでこれを行うには、基本的にピボットクエリを実行する必要があります。これは書くのが難しく、実行するのがひどく非効率的です。

従業員のすべてのデータを取得することをお勧めします。

SELECT e.*, f.label
FROM Data AS is_employee
JOIN Data AS e USING (user_id)
JOIN Fields AS f ON e.field_id = f.id
WHERE (is_employee.field_id, is_employee.value) = (1, 'Yes');

そして、それをPHPコードの連想配列のコレクションに再編成します。

while ($row = $stmt->fetch()) {
  $data[ $row['user_id'] ][ $row['label'] ] = $row['value'];
}
于 2012-11-20T20:43:06.237 に答える
2

これは基本的にはですPIVOTが、MySQL にはPIVOT関数がないため、集計関数とCASEステートメントを使用して複製できます。

静的バージョンは、列に変換するすべての値がわかっている場合です (これらはフィールド名です)。

select 
  d.user_id,
  max(case when f.name = 'IS_EMPLOYEE' then d.value else null end) IS_EMPLOYEE,
  max(case when f.name = 'EM_AVATAR' then d.value else null end) EM_AVATAR,
  max(case when f.name = 'EM_JOBTITLE' then d.value else null end) EM_JOBTITLE,
  max(case when f.name = 'EM_COMPANY' then d.value else null end) EM_COMPANY,
  max(case when f.name = 'EM_PHONE' then d.value else null end) EM_PHONE,
  max(case when f.name = 'EM_ORDER' then d.value else null end) EM_ORDER
from data d
left join fields f
  on f.id = d.FIELD_ID
group by d.user_id

デモで SQL Fiddle を参照してください

結果:

| USER_ID | IS_EMPLOYEE |                       EM_AVATAR |                EM_JOBTITLE | EM_COMPANY |       EM_PHONE | EM_ORDER |
---------------------------------------------------------------------------------------------------------------------------------
|       1 |         YES |                          (null) |                      Owner | Acme, Inc. |   123-456-7987 |   (null) |
|       6 |          NO | http://example.com/avi/avi.jpeg |                        CEO |       Acme | (123) 734-5555 |   (null) |
|       7 |          NO | http://example.com/avi/avi.jpeg |               VP, Services |       Acme | (913) 963-5555 |   (null) |
|       8 |          NO | http://example.com/avi/avi.jpeg |        General Information |       Acme | (123) 213-5555 |   (null) |
|       9 |          NO | http://example.com/avi/avi.jpeg |                  VP, Sales |       Acme | (123) 210-5555 |   (null) |
|      10 |          NO | http://example.com/avi/avi.jpeg |                  President |       Acme | (123) 734-5555 |   (null) |
|      11 |          NO | http://example.com/avi/avi.jpeg |      Operations Supervisor |       Acme | (123) 259-5555 |   (null) |
|      12 |          NO | http://example.com/avi/avi.jpeg |        Services Supervisor |       Acme | (123) 573-5555 |   (null) |
|      14 |          NO | http://example.com/avi/avi.jpeg |          Senior Accountant |       Acme | (123) 213-5555 |   (null) |
|      31 |         YES |                          (null) | Sales and Customer Support | Acme, Inc. |   123-623-5555 |   (null) |

列に変換する値の数が不明な場合は、準備済みステートメントを使用して SQL を動的に生成できます。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when f.name = ''',
      name,
      ''' then d.value end) AS ',
      name
    )
  ) INTO @sql
FROM fields;

SET @sql = CONCAT('SELECT d.user_id, ', @sql, ' 
                  from data d
                  left join fields f
                    on f.id = d.FIELD_ID
                   GROUP BY d.user_id');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

デモで SQL Fiddle を参照してください

どちらも同じ結果になります。

次に句を追加してWHERE、不要な行を除外できます。

于 2012-11-20T20:46:07.653 に答える