我有两个表消息和用户我想知道哪些用户收到了消息,但查询只返回一条消息。
我的架构如下
讯息
msg_id | msg_content | recipients |
-----------------------------------
1 | Hello world | 1,2,3,4,5
2 | Test | 1,3,5
3 | Welcome | 1,2,4
用户
uid | fname | lname |
---------------------------
1 | John |Doe |
2 | Jane |Doe |
3 | Mark |Someone |
4 | Mary |lady |
5 | Anthony |Doe |
所以我很乐意将结果视为
msg_id | msg_content | recipients |
-----------------------------------
1 | Hello world | John,Jane,Mark,Mary,Anthony
2 | Test | John,Mark,Anthony
3 | Welcome | John,Jane,Mary
所以我这样做我的查询
SELECT msg_id,msg_content,fname AS recepients FROM messages a
LEFT JOIN users ON uid IN(a.recipients)
当我运行该查询时,我只收到一个收件人。请指教。感谢。
答案 0 :(得分:2)
我认为您必须使用替代方法来创建表
消息
msg_id | msg_content |
----------------------
1 | Hello world |
2 | Test |
3 | Welcome |
用户
uid | fname | lname |
---------------------------
1 | John |Doe |
2 | Jane |Doe |
3 | Mark |Someone |
4 | Mary |lady |
5 | Anthony |Doe |
users_has_messages
uhm_id | uid | msg_id |
---------------------------
1 | 1 | 1 |
2 | 2 | 1 |
3 | 3 | 1 |
4 | 2 | 2 |
5 | 1 | 3 |
然后你可以使用你的代码
答案 1 :(得分:1)
好的,所以这个架构不是最好的(使用逗号分隔的ID列表不是一个好主意,并且任何连接的性能都会非常糟糕)。最好的办法是让@Thilina提到的第三个表格映射到msg_id&#39s。
也就是说,这个查询可能会完成你之后的事情:
SELECT msg_id,msg_content,GROUP_CONCAT(fname) AS recepients FROM messages a
LEFT JOIN users ON FIND_IN_SET(uid, a.recipients)
GROUP BY msg_id
答案 2 :(得分:0)
我在Oracle 12c中尝试了这个,它运行正常。
基本上我所做的就是 - 将userid与收件人字段分开,并使用此列。 - 加入USERS表以获取用户名 - 使用LISTAGG函数将其聚合回来。
对于MySql,我们需要找到相应的函数来分隔逗号之间的ID,将其转换为行和聚合。但固有的逻辑是一样的。
with users (user_id,fname) as (
select 1 ,'John' from dual union
select 2 ,'Jane' from dual union
select 3 ,'Mark' from dual union
select 4 ,'Mary' from dual union
select 5 ,'Anthony' from dual
),
messages(msg_id, msg_content,recipients) as(
select 1,'Hello world','1,2,3,4,5' from dual union
select 2 , 'Test' ,'1,3,5' from dual union
select 3,' Welcome','1,2,4' from dual
),
flat as(
select msg_id,msg_content,
REGEXP_SUBSTR (recipients, '[^,]+', 1, COLUMN_VALUE) as user_id
from messages,
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(recipients ,',' ) + 1
) AS SYS.ODCINUMBERLIST
)
)
),
unames as
( select f.msg_id,f.msg_content,u.fname from flat f inner join users u
on f.user_id = u.user_id
order by f.msg_id
)
SELECT msg_id,msg_content,LISTAGG(fname, ',') WITHIN GROUP (ORDER BY fname) as recipients
from unames
group by msg_id,msg_content