复杂连接(加入连接)

时间:2014-12-11 20:44:12

标签: mysql sql join left-join inner-join

我有4张桌子:预订,地址,search_address& search_address_log

表:(相关cols)

预订:(pickup_address_id,dropoff_address_id)

地址:(address_id,邮政编码)

search_address:(address_id,postcode)

search_address_log:(id,from_id,to_id)


我需要做的是从预订和search_address_log获取计数 由拾取/降落&分组从/到邮政编码。

我可以为每个人单独做这件事:

预订:

SELECT
a1.postcode b_From,
a2.postcode b_to,
COUNT(*) b_count
FROM booking b
INNER JOIN address a1 ON b.pickup_address_id = a1.address_id
INNER JOIN address a2 ON b.destination_address_id = a2.address_id
GROUP BY b_From, b_To
ORDER BY COUNT(*) DESC
LIMIT 10

search_address_log:

SELECT
sa1.postcode s_From, 
sa2.postcode s_To,
COUNT(*) s_count
FROM search_address_log sal
INNER JOIN search_address sa1 ON sal.from_id=sa1.address_id
INNER JOIN search_address sa2 ON sal.to_id=sa2.address_id
GROUP BY s_From, s_To
ORDER BY COUNT(*) DESC
LIMIT 10

返回表格,如:

|    b_To   b_From    b_count   ||     s_To   s_From    s_count   |
|    x      y         10        ||     x       y       50         |
|    a      b         5         ||     a       b       60         |

我需要什么:

|    To    From    b_count   s_count   |
|    x      y         10       50      |
|    a      b         5        60      |

谢谢,

乔治

3 个答案:

答案 0 :(得分:1)

从技术上讲,你想要的是full outer join,但MySQL并不支持。但是,以下内容应该可以执行您想要的操作 - 获取两列的每个fromto值的摘要:

SELECT b_from, b_to, sum(b_count) as b_count, sum(s_count) as s_count
FROM ((SELECT a1.postcode as b_From, a2.postcode as b_to, COUNT(*) as b_count, 0 as s_count
       FROM booking b INNER JOIN
            address a1
            ON b.pickup_address_id = a1.address_id INNER JOIN
            address a2
            ON b.destination_address_id = a2.address_id
       GROUP BY b_From, b_To
      ) UNION ALL
      (SELECT sa1.postcode as s_From, sa2.postcode as s_To, 0, COUNT(*) as s_count
       FROM search_address_log sal INNER JOIN
            search_address sa1
            ON sal.from_id = sa1.address_id INNER JOIN
            search_address sa2
            ON sal.to_id = sa2.address_id
       GROUP BY b_From, b_To
      )
     ) ft
GROUP BY s_From, s_to;

答案 1 :(得分:0)

提案:选择地址 - 获取往/返对的计数,然后按邮政编码添加

SELECT t.postcode, f.postcode, SUM(sal.count), SUM(b.count) 
    FROM search_address t, search_address f
    LEFT JOIN ( SELECT from_id, to_id, COUNT(*) count 
                    FROM search_address_log GROUP BY from_id, to_id ) sal 
        ON sal.from_id=f.address_id AND sal.to_id=t.address_id
    LEFT JOIN ( SELECT pickup_address from_id, destination_address_id to_id, COUNT(*) count 
                    FROM booking GROUP BY from_id, to_id) b
        ON b.from_id=f.address_id AND b.to_id=t.address_id
    WHERE sal.count > 0 OR b.count > 0
    GROUP BY t.postcode, f.postcode;

这将根据平方的地址数量进行扩展,这可能会比另一个答案中概述的“生成独立摘要然后联合它们”方案更糟糕。然而,它更简洁一点。

答案 2 :(得分:0)

如果每个预订都有一个pickup_address和一个destination_address,并且每个search_address_log from_id和to_id都有一个搜索地址,并且预订中的代码与搜索地址日志中的代码相同,那么您可以像

select t1.b_from, t1.b_to,  t1.b_count, t2.s_count from
(SELECT
a1.postcode b_From,
a2.postcode b_to,
COUNT(*) b_count
FROM booking b
INNER JOIN address a1 ON b.pickup_address_id = a1.address_id
INNER JOIN address a2 ON b.destination_address_id = a2.address_id
GROUP BY b_From, b_To) t1
inner join 
(SELECT
sa1.postcode s_From, 
sa2.postcode s_To,
COUNT(*) s_count
FROM search_address_log sal
INNER JOIN search_address sa1 ON sal.from_id=sa1.address_id
INNER JOIN search_address sa2 ON sal.to_id=sa2.address_id
GROUP BY s_From, s_To) t2 on (t1.b_from =  t2.s_from and t1.b_to = t2.s_to)