来自多个表的MySQL JOIN语句

时间:2017-05-09 21:57:09

标签: mysql sql join pivot-table entity-attribute-value

我有一个旧的数据库,来自一个被遗弃的" Joomgalaxy" Joomla插件。

有三个表格joomgalaxy_entriesjoomgalaxy_fieldsjoomgalaxy_entries_data

id表中的entriesentry_id表中的entries_data匹配,但实际字段名称保存在另一个表fields < / p>

有人可以帮助我使用正确的SQL语句来获取结果,就像您在终极目标中看到的那样?我的MySQL知识非常基础,从我的搜索中听起来我需要使用LEFT JOIN,但我不知道如何使用field_name中的值作为返回值的列名

谢谢!!

joomgalaxy_entries

---------------------------------------
| id | title | longitude | latitude   |
---------------------------------------
| 50  | John | -79.333333 | 43.669999 |
| 51  | Bob  | -79.333333 | 43.669999 |
---------------------------------------

joomgalaxy_fields

这只是下面两个例子,为了简单起见,不仅仅是这两个,所以它必须能够使用field_name作为列名动态处理。

--------------------------------
| id | field_type | field_name |
--------------------------------
| 1  | textbox    | websiteurl |
| 2  | dropdown   | occupation |
--------------------------------

joomgalaxy_entries_data

&#34;技术上&#34;不应该有任何重复的条目(fieldidentry_id),所以根据我的理解,不应该影响使用上面的field_name作为列名,但是如果最终成为一个怎么办?

-------------------------------------
| fieldid | field_value | entry_id |
-------------------------------------
|   1     | google.com  |    50    | 
|   2     | unemployed  |    50    |
|   1     | doctor.com  |    51    | 
|   2     | doctor      |    51    |
-------------------------------------

终极目标

最终尝试获得这种类型的结果,然后我可以在MySQL Workbench中使用该语句来导出如下所示的数据:

------------------------------------------------------------------
| id | title | longitude  | latitude   | websiteurl | occupation |
------------------------------------------------------------------
| 50  | John | -79.333333 | 43.669999  | google.com | unemployed |
| 51  | Bob  | -79.333333 | 43.669999  | doctor.com | doctor     |
------------------------------------------------------------------

修改 不仅仅是两个字段websiteurloccupation,我只是将这两个字段用作示例,有许多字段都是不同的,因此理论上从field_name中提取值将用于列名称

5 个答案:

答案 0 :(得分:1)

您可以使用某些条件逻辑(如CASE语句)以及max()min()等聚合函数将这些值作为列返回:

SELECT je.id,
  je.title, 
  je.longitude,
  je.latitude,
  max(case when jf.fieldid = 1 then jed.field_value end) as WebsiteUrl,
  max(case when jf.fieldid = 2 then jed.field_value end) as Occupation
FROM  joomgalaxy_entries je
INNER JOIN joomgalaxy_entries_data jed
  on je.id = jed.entry_id
GROUP BY je.id,
  je.title, 
  je.longitude,
  je.latitude

如果要返回所有joomgalaxy_entries,即使在其他表中没有要连接的匹配行,使用INNER JOIN也只会返回每个表中包含值的joomgalaxy_entries行,然后将INNER JOIN更改为LEFT JOIN。

答案 1 :(得分:1)

您可以编写一个简单的SELECT查询,如下所示:

SELECT je.id, je.title, je.longitude, je.latitude, 
(SELECT field_value FROM joomgalaxy_entries_data WHERE fieldid = 1 AND entry_id = je.id) AS websiteurl,
(SELECT field_value FROM joomgalaxy_entries_data WHERE fieldid = 2 AND entry_id = je.id) AS occupation
FROM joomgalaxy_entries je;

答案 2 :(得分:0)

第一步很简单:

SELECT JE.id, JE.title, JE.longitude, JE.latitude
FROM joomgalaxy_entries JE

现在你需要加入:

SELECT JE.id, JE.title, JE.longitude, JE.latitude,
       JD.*
FROM joomgalaxy_entries JE
JOIN joomgalaxy_entries_data JD
  ON JE.id = JD.entry_id

现在您需要将行转换为列

SELECT JE.id, JE.title, JE.longitude, JE.latitude,
       MIN(CASE WHEN fieldid = 1 THEN JD.field_value END) as WebsiteUrl,
       MIN(CASE WHEN fieldid = 2 THEN JD.field_value END) as Occupation
FROM joomgalaxy_entries JE
JOIN joomgalaxy_entries_data JD
  ON JE.id = JD.entry_id
GROUP BY JE.id, JE.title, JE.longitude, JE.latitude

这取决于你每个条目只有两个字段,如果字段数是动态的,你需要一个不同的方法。

答案 3 :(得分:0)

这应该有效:

select id, title, longitude, latitude,
    (select field_value from joomgalaxy_entries_data jed
      where fieldid = (select id from joomgalaxy_fields
                        where field_name = 'websiteurl')
        and jed.entry_id = je.id
       ) as websiteurl,
    (select field_value from joomgalaxy_entries_data jed
      where fieldid = (select id from joomlgalaxy_fields
                        where field_name = 'occupation')
        and jed.entry_id = je.id) as occupation
  from joomgalaxy_entries je;

请注意,左边连接的原因是,如果siteurl或者占用为null,则无论如何,此解决方案应该适用于该情况。

答案 4 :(得分:0)

嗯,这肯定会让它变得更难...... :)老实说,我不确定你用静态SQL查询可以提出什么问题。但是,如果我错了,我相信有人会说出来。

那就是说,我可以尝试一些选项:

选项1 - 动态生成SQL

假设这是mysql,如果执行以下SQL,它将动态生成子查询:

select concat('(select field_value from joomgalaxy_entries_data jed ',
              'where fieldid = (select id from joomgalaxy_fields ',
              'where field_name = ''', field_name, ''') ',
              'and jed.entry_id = je.id) as ', field_name, ',')
              from joomgalaxy_fields;

获取该命令的结果,将其复制粘贴到文本编辑器中,并在开头添加以下内容:

select id, title, longitude, latitude,

最后的其余部分:

from joomgalaxy_entries je;

然后运行新的超级查询,根据数据库中的数据量,获取一份副本,午餐或晚安睡眠。

或者,您可以将所有这些添加到存储过程中,这样您就不必手动编辑SQL。另请注意,我的语法适用于MySQL。其他数据库具有不同的连接运算符,因此您可能必须解决此问题(如果适用)。此外,有50多个子查询,这个超级查询很可能会很慢,可能太慢,无法使这个选项可行。

选项2 - 按照您想要的方式创建一个表格并填充它

希望这是不言自明的,但只需创建一个包含joomgalaxy_fields表中所有必需列的新表。然后用一长串应该是非常简单的sql命令分别填充每一列。当然,如果数据库不再使用,我相信你指出这个选项是可行的。从那里结果就是:

select * from my_new_table;