0

わかりました、私はまだSQLの初心者であり、これをまだ理解できません。私には4つのテーブルがあります:companys、persons、details、person_details。

companies: 
id, compname
(1, ACME), 
(2, ACME Group), ...

persons: 
id, name, lastname, company id
(1, donald, duck, 1), 
(2, lucky, luke, 1), 
(3, mickey, mouse, 2)

details: 
id, description
(1, 'weight'), 
(2, 'height'), 
(3, 'haircolor'), ...

person_details: 
id, persons id, details id, value
(1, 1, 1, 70), 
(2, 1, 3, 'red'), 
(3, 2, 1, 90), 
(4, 3, 2, 180)

ご覧のとおり、すべての人がすべての詳細を持っているわけではなく、利用可能な詳細のリストはさまざまです。

ここで、特定の個人IDと詳細IDの配列について、会社名とID、個人名と姓、詳細名と、提供された配列内の各詳細の値を含む行を取得したいと思います。たとえば、persons(1,2)、details(1,3)の結果は次のようになります。

companies.id, companies.name, name, lastname, details.description, person_details.value,...    
    1, ACME, donald, duck, 'weight', 70, 'haircolor', 'red'
    2, ACEM, lucky, luke, 'weight', 90, 'haircolor', null

助けてください...

4

1 に答える 1

1

説明に基づくと、データをピボットしたいようですが、残念ながらMySQLにはピボットCASE関数がないため、ステートメントを含む集計関数を使用してデータを複製する必要があります。

説明の値が事前にわかっている場合は、クエリを次のようにハードコーディングできます。

select c.id,
  c.compname,
  p.name,
  p.lastname,
  max(case when d.description = 'weight' then pd.value end) weight,
  max(case when d.description = 'haircolor' then pd.value end) haircolor,
  max(case when d.description = 'height' then pd.value end) height
from companies c
left join persons p
  on c.id = p.`company id`
left join person_details pd
  on p.id = pd.`persons id`
left join details d
  on pd.`details id` = d.id
-- where p.id in (1, 2)
group by c.id, c.compname, p.name, p.lastname

SQL FiddlewithDemoを参照してください

値の数が不明な場合は、プリペアドステートメントを使用して、次のように動的にこれを生成できます。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN d.description = ''',
      description,
      ''' then pd.value end) AS ',
      description
    )
  ) INTO @sql
FROM details;

SET @sql = CONCAT('SELECT c.id,
                      c.compname,
                      p.name,
                      p.lastname, ', @sql, ' 
                  from companies c
                  left join persons p
                    on c.id = p.`company id`
                  left join person_details pd
                    on p.id = pd.`persons id`
                  left join details d
                    on pd.`details id` = d.id
                  -- where p.id in (1, 2)
                  group by c.id, c.compname, p.name, p.lastname');

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

SQL FiddlewithDemoを参照してください

どちらのバージョンも結果を生成します。

| ID |   COMPNAME |   NAME | LASTNAME | WEIGHT | HEIGHT | HAIRCOLOR |
---------------------------------------------------------------------
|  1 |       ACME | donald |     duck |     70 | (null) |       red |
|  1 |       ACME |  lucky |     luke |     90 | (null) |    (null) |
|  2 | ACME Group | mickey |    mouse | (null) |    180 |    (null) |
于 2012-12-31T14:23:34.227 に答える