如何联合2选择而不重复

Posted

技术标签:

【中文标题】如何联合2选择而不重复【英文标题】:How to union 2 select without duplication 【发布时间】:2020-03-05 21:39:57 【问题描述】:

重复问题

这是否可以在使用 Codeigniter mysql 的单个查询中使用 codeigniter 获取此输出?

oid |  count(waiters) as total_waiters
----+-------------------------------
1   |      1 <-- john will be count as 1 even if assigned to 2 room
2   |      1
3   |      2 <-- count is 2 because different waiters are assigned with different room
4   |      0

订单表

oid |  name 
----+-------
1   |   aa   
2   |   bb   
3   |   cc   
4   |   dd     

餐桌

Rid |  oid  |  waiter_assigned
----+-------+-----------------
1   |   1   |     john
2   |   1   |     john
3   |   2   |     john
4   |   3   |     mike
5   |   3   |     dude

我尝试使用联合

$this->db->select('o.oid, "" AS tot_book_thera');
$this->db->from('order o');
$query1 = $this->db->get_compiled_select();

$this->db->select('r.oid, count(r.waiter_assigned) AS total_waiters');
$this->db->from('room r');
$this->db->group_by('r.waiter_assigned');
$query2 = $this->db->get_compiled_select();

但我明白了……

oid |  count(waiters) as total_waiters
----+-------------------------------
1   |      1 
2   |      1
3   |      2
1   |      '' <-- not sure how to combine it with the 1st or how to exclude this or remove this...

非常感谢任何帮助,谢谢大家!

【问题讨论】:

您应该阅读GROUP BY 应该如何成为handled .. 看到select('o.*,group_by('o.oid')...select('o.*,group_by('r.waiter_assigned') 告诉我你没有提示它可能有什么问题,或者如何在 SQL 语言中正确使用GROUP BY .. @RaymondNijland 我明白了,但我不知道如果我应该使用GROUP BY 或其他代码,该使用什么...... 这些查询有效的唯一方法是何时可以使用函数依赖。无论如何,让我看看我是否理解输出背后的逻辑.. @RaymondNijland 嗯,好吧,如果我删除我的组,会有可能的解决方案吗?感谢您的帮助,如果需要,我会更新我的标题和其他详细信息以消除混乱 无论如何,需要先做点别的事情,这里获得该结果集的主要问题是您需要加入,并且在oid 上使用GROUP BY“取消重复”,因为您还需要使用COUNT(..)从 MySQL 的角度来看,oidRid 并没有真正明确的分离,为什么你不计算分离.. 但我现在需要去几个小时,而不必是时候格式化整个查询和答案了,但请考虑 db-fiddle.com/f/s5B1Zxp5tSrf87JcSQToKW/0 和 db-fiddle.com/f/s5B1Zxp5tSrf87JcSQToKW/0 之间的区别 【参考方案1】:

你的想法是对的。但正如其他人所说,GROUP BY 是你最好的朋友。此外,使用 DISTINCT 可以避免为同一订单计算两次服务员。你的代码应该是这样的

// An inner select query whose purpose is to count all waiter per room
// The key here is to group them by `oid` since we are interested in the order
// Also, in the count(), use DISTINCT to avoid counting duplicates
$this->db->select('room.oid, count(DISTINCT room.waiter_assigned) AS total_waiters');
$this->db->from('room');
$this->db->group_by('room.oid');
$query1 = $this->db->get_compiled_select();

// If you run $this->db->query($query1)->result(); you should see
oid |  total_waiters
----+-------------------------------
1   |      1
2   |      1
3   |      2

// This is how you would use this table query in a join.
// LEFT JOIN also considers those rooms without waiters
// IFNULL() ensures that you get a 0 instead of null for rooms that have no waiters
$this->db->select('order.oid, order.name, IFNULL(joinTable.total_waiters, 0) AS total_waiters');
$this->db->from('order');
$this->db->join('('.$query1.') joinTable', 'joinTable.oid = order.oid', 'left');
$this->db->get()->result();

// you should see
oid |  name     |  total_waiters
----+-----------+-------------------------
1   |  aa       |      1
2   |  bb       |      1
3   |  cc       |      2
4   |  dd       |      0

这是原始 SQL 语句

SELECT order.oid, order.name, IFNULL(joinTable.total_waiters, 0) AS total_waiters
FROM order
LEFT JOIN (
    SELECT room.oid, count(DISTINCT room.waiter_assigned) AS total_waiters  
    FROM room
    GROUP BY room.oid
) joinTable ON joinTable.oid = order.oid

【讨论】:

谢谢@yesigye,它确实有效!想知道在获得总服务员方面是否比 make forloop 更快...... 对于像这样的小查询,性能并不重要。我建议您使用 DBMS,因为 DBMS 旨在优化连接。使用 php 将需要您使用循环和 if else 语句,您必须自己维护和优化。

以上是关于如何联合2选择而不重复的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 从具有重复引用条目的联合表中选择唯一记录

如何打印除一个以外的对象,而不删除任何内容(JavaScript)[重复]

SQL 从多个表中选择列而不重复数据

xquery 随机选择文件而不重复选择

C#实体框架:添加/插入记录并选择他而不保存更改[重复]

在不重复选择的情况下找到所有可能的组合?