【问题标题】:MySQL join vs unionMySQL加入与联合
【发布时间】:2017-11-02 00:49:45
【问题描述】:

我有一个表 message,其中包含 id(主键)、parent_id(自我的外键)、owner_id(创建者用户 ID)和 message(实际消息)列)。

我现在正在尝试检索由特定 owner_id 拥有的所有列,或者具有指向由特定 owner_id 拥有的另一条记录的 parent_id 的所有列。

我已经成功地做到了:

select * from message m1
left join message m2 on m1.id = m2.parent_id
where m1.owner_id = 1;

但是,我得到的结果是这样的(在右侧添加了m2 列):

id  parent_id   owner_id    message         id      parent_id   owner_id    message
------------------------------------------------------------------------------------------
1   NULL        1           First message   3       1           2           Third message
1   NULL        1           First message   4       1           2           Fourth message
2   NULL        1           Second message  NULL    NULL        NULL        NULL

...当我想要这样的时候(所有唯一匹配列的简单列表,顺序并不重要):

id  parent_id   owner_id    message
------------------------------------------
1   NULL        1           First message
3   1           2           Third message
4   1           2           Fourth message
2   NULL        1           Second message

我意识到我可以使用 union 来做到这一点,但我看不出任何设计联合查询的方法,而不会使其效率极低。

你会如何解决这样的问题?

谢谢。

编辑

这是我正在使用的表格:

create table message (
   id int(11) unsigned auto_increment primary key,
   parent_id int(11) unsigned default null,
   owner_id int(11) unsigned not null,
   message varchar(255) default null,

   index (parent_id),

   foreign key (parent_id) references message(id) on update cascade on delete cascade
) engine=innodb default charset=utf8;

【问题讨论】:

  • 请编辑您的问题并显示您开始使用的数据。

标签: mysql sql join union


【解决方案1】:

左连接和需求的直译就可以了。

select m.* from message m 
left join message p on m.parent_id=p.id
where m.owner_id=1 or p.owner_id=1
order by m.id

上面的SQL选择owner id为1或parent的owner id为1的消息。

SQLFiddle Example

【讨论】:

  • 好吧,我这里不关心p的所有者ID,我希望pparent_id的记录的owner_idowner_id 1。
  • 你的意思是mparent_idp 是父级。
  • 但这就是你想要的对吧?消息本身的所有者 ID 是1,或者消息的父级的所有者 ID 是 1。再看一下查询并查看链接中的示例。
  • 啊,是的。你说的对。对不起,我想得有点落后。谢谢你的帮助! :)
【解决方案2】:

如果我理解正确,您需要任何父或所有者为 1 的消息。然后您希望按层次排序。因为您只寻找一个 id,所以我认为这可以满足您的要求:

select m.*
from message m
where 1 in (m.id, m.parent_id)
order by coalesce(m.parent_id, m.id), id;

【讨论】:

  • 嗯,父级指的是同一张表中的id,而不是owner_id。使用联合的解决方案(但性能噩梦)是:select * from message where owner_id = 1 union select * from message where parent_id in (select id from message where owner_id = 1)
  • @HelgeTalvikSöderström 。 . .我想我在whereorder by 之间发现了这一点。我更新了答案。
【解决方案3】:

您可以使用联合进行以下查询:

select id from message where owner_id="USER" --all the records for which the owner is directly "USER"
union all -- to remove duplicates generated by the union if any
select m1.id from message m1, message m2 where m1.parent_id=m2.parent_id and m1.id != m2.id and m2.owner_id="USER"
-- all the records from m2 that share the same parent_id as m1 (but that are not the same id to avoid taking the m1 record itself)
-- for which m2.owner is the specified one

祝你好运!干杯

【讨论】:

    猜你喜欢
    • 2011-07-15
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 2012-01-30
    相关资源
    最近更新 更多