我已经签约工作的应用程序有一个非常烦人的问题.
由于兼容性原因我无法修改的数据库结构很乱.它基本上是一个多对多,多对多,一对一的关系.它是这样的:
联系
---------------------------
| contact_id | name | ... |
---------------------------
| 1 | foo | |
---------------------------
metadefinition
-----------------------------
| metadefinition_id | name |
-----------------------------
| 1 | title |
-----------------------------
| 2 | job |
-----------------------------
contact_metadata
----------------------------
| contact_id | metadata_id |
----------------------------
| 1 | 1 |
----------------------------
| 1 | 2 |
----------------------------
元数据
-------------------------------------------
| metadata_id | metadefinition_id | value |
-------------------------------------------
| 1 | 1 | mrs |
-------------------------------------------
| 2 | 2 | coder |
-------------------------------------------
因此,对于单个联系人,我想搜索所有这些并获得如下内容:
-----------------------------------------------------
| contact_id | name | metadata.title | metadata.job |
-----------------------------------------------------
| 1 | foo | mrs | coder |
-----------------------------------------------------
那么现在到目前为止我已经尝试过了.我可以提前获取元定义列表,这不是一个真正的问题.所以我构建了一个这样的查询:
SELECT contact.*,m1.value AS `metadata.title` FROM contact
LEFT JOIN contact_metadata ON contact.contact_id = contact_metadata.contact_id
LEFT JOIN metadata m1 ON contact_metadata.metadata_id = m1.metadata_id AND m1.metadefinition_id = 1
GROUP BY contact_id
这适用于单个元定义,我得到这样的东西:
--------------------------------------
| contact_id | name | metadata.title |
--------------------------------------
| 1 | foo | mrs |
--------------------------------------
但是,如果我尝试使用两个:
SELECT contact.*,m1.value AS `metadata.title`,m2.value AS `metadata.job` FROM contact
LEFT JOIN contact_metadata ON contact.contact_id = contact_metadata.contact_id
LEFT JOIN metadata m1 ON contact_metadata.metadata_id = m1.metadata_id AND m1.metadefinition_id = 1
LEFT JOIN metadata m2 ON contact_metadata.metadata_id = m2.metadata_id AND m2.metadefinition_id = 2
GROUP BY contact_id
我明白了:
-----------------------------------------------------
| contact_id | name | metadata.title | metadata.job |
-----------------------------------------------------
| 1 | foo | mrs | NULL |
-----------------------------------------------------
如果我删除GROUP BY子句,当然,我得到:
-----------------------------------------------------
| contact_id | name | metadata.title | metadata.job |
-----------------------------------------------------
| 1 | foo | mrs | NULL |
-----------------------------------------------------
| 1 | foo | NULL | coder |
-----------------------------------------------------
只要查询时间相对可接受,我就可以接受任何事情(考虑到结构,如果100000条记录需要10秒钟,那么它总比没有好)
是不是临时表,存储过程,我不在乎,只要我不用改变实际的数据库结构.
相信我,当它成为改造的时候,我很高兴把整件事搞砸.
有解决方案吗,有可能吗?
提前致谢.
解决方法:
我使用了一对相关的子查询.就像是
SELECT c.*
,( Select value from metadata m1
INNER JOIN contact_metadata cm
on cm.metadata_id = m1.metadata_id
WHERE m1.metadefinition_id = 1
AND cm.contact_id = c.contact_id )AS `metadata.title`
,( Select value from metadata m1
INNER JOIN contact_metadata cm
ON cm.metadata_id = m1.metadata_id
WHERE m1.metadefinition_id = 2
AND cm.contact_id = c.contact_id )AS `metadata.job`
FROM contact c
WHERE c.contact_id = 1
标签:mysql,many-to-many 来源: https://codeday.me/bug/20190721/1496248.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。