SQL中的联接表,其中新列名基于另一列的联接表值

时间:2019-01-18 16:29:46

标签: mysql sql

我有2个表,我正在尝试将第二个表的内容加入第一个表。本质上,我想以包含第一张表中的所有字段以及第二张表中的所有相关行,第二张表中列内容之后的名称的项目列表结尾。

表A

+----+--------+---------------------+--------+
| ID | Title  |        Date         | Etc... |
+----+--------+---------------------+--------+
|  1 | QWERTY | 0000-00-00:00:00:00 |    ... |
|  2 | TEST   | 0000-00-00:00:00:00 |    ... |
|  3 | ASDF   | 0000-00-00:00:00:00 |    ... |
|  4 | IOP    | 0000-00-00:00:00:00 |    ... |
+----+--------+---------------------+--------+

表B

+----+------------+------+------------+
| ID | Table_A_ID | Key  |   Value    |
+----+------------+------+------------+
|  1 |          1 | Name | John       |
|  2 |          2 | Name | Brad       |
|  3 |          1 | DOB  | 2000-01-16 |
+----+------------+------+------------+

所以我希望能够从表A中选择*,并以某种方式结束以下操作

+----+--------+---------------------+--------+------+------------+
| ID | Title  |        Date         | Etc... | Name |    DOB     |
+----+--------+---------------------+--------+------+------------+
|  1 | QWERTY | 0000-00-00:00:00:00 |    ... | John | 2000-01-16 |
|  2 | TEST   | 0000-00-00:00:00:00 |    ... | Brad |            |
|  3 | ASDF   | 0000-00-00:00:00:00 |    ... |      |            |
|  4 | IOP    | 0000-00-00:00:00:00 |    ... |      |            |
+----+--------+---------------------+--------+------+------------+

关键是我不知道关键是什么

不幸的是,我不知道用什么来谷歌搜索它,我一直在通过内,左,右连接进行查找,而这些似乎并没有执行我想做的事情。

3 个答案:

答案 0 :(得分:1)

这可以通过在TableB上使用两个JOIN来实现,例如:

SELECT
    ta.id,
    ta.date,
    ta.etc,
    tb.value Name,
    td.value DOB
FROM
    tableA ta
    INNER JOIN tableB tb ON tb.table_a_id = tb.id AND tb.key = 'Name'
    INNER JOIN tableB td ON td.table_a_id = ta.id AND td.key = 'DOB'

使用此查询,仅显示在TableB中确实具有名称和DOB的记录。如果要避免过滤掉这些“不完整”的记录,可以使用LEFT JOIN代替INNER JOIN。

答案 1 :(得分:0)

Select a.*, 
(select TOP 1  b.DOB from b where b.table_a_id = a.id and b.key = 'dob'), 
(select TOP 1 b.ame from b where b.table_a_id = a.id and b.key = 'name') 
from a

您必须使用子选择才能获得该结果

答案 2 :(得分:0)

您正在寻找透视键值的关键。您可以像这样手动进行操作:

select a.*
     , max(case b.key when 'Name' then b.value end) Name
     , max(case b.key when 'DOB' then b.value end) DOB
  from TableA a
  left join TableB b
    on a.id = b.table_a_id
  group by a.id
      , a.title
      , a.date
      , a.etc

如果在TableA中给定记录的每个属性只有一个,则上述查询将起作用,否则它将为您提供最大的价值。如果需要多个值,可以为每个属性生成一个序列,如下面名为B的子选择所示:

select a.ID
     , b.Seq
     , a.Title
     , a.Date
     , a.Etc
     , max(case b.key when 'Name' then b.value end) Name
     , max(case b.key when 'DOB' then b.value end) DOB
  from TableA a 
  left join (select @Seq:=case
                       when @aid=b.Table_A_ID and @key=b.key
                       then @Seq + 1
                       else 1
                     end Seq
                   , @aid:=b.Table_A_ID Table_A_ID
                   , @key:=b.key `Key`
                   , b.value
                from tableB b
               order by table_a_id, b.key) b
     on a.id = b.table_a_id
  group by a.id, a.title, a.date, a.etc, b.Seq;

这与@GMB的响应不同之处在于,它只会返回每个属性一次,并且在每个属性的值较少的行中为空,而@GMB的解决方案将返回给定行所有属性的CROSS乘积。