2017-10-10 68 views
2

我具备这些表的数据库:如何有SQL查询2级的子查询分为

  1. 用户(ID,电子邮件)
  2. 旅行(ID,driver_id)
  3. MatchedTrips(ID,trip_id )

我需要为每个用户获得他创建的旅行总数除以找到的总匹配数。

我一直在为此构建原始SQL查询。这是我试过的,并且确定它远没有正确。

SELECT 
    users.email, 
    total_trips.count1/total_matches.count2 
FROM users CROSS JOIN (SELECT 
     users.email, 
     count(trips.driver_id) AS count1 
     FROM trips 
     INNER JOIN users ON trips.driver_id = users.id 
     GROUP BY users.email) total_trips 
     CROSS JOIN (SELECT users.email, count(matches.trip_id) AS count2 
        FROM matches 
        LEFT JOIN trips ON matches.trip_id = trips.id 
        LEFT JOIN users ON trips.driver_id = users.id 
        GROUP BY users.email) total_matches; 

回答

1

最简单的方法可能是使用count(distinct)

select u.email, 
     count(distinct t.id) as num_trips, 
     count(distinct m.id) as num_matches, 
     (count(distinct t.id)/count(distinct m.id)) as ratio 
from users u left join 
    trips t 
    on t.driver_id = u.id left join 
    matches m 
    on m.trip_id = t.trip_id 
group by u.email; 

注意:如果邮件是唯一的,那么查询可以简化。在某些情况下,count(distinct)可能很昂贵。

+0

我认为这个查询需要处理除零的情况,并且是的电子邮件是唯一的。感谢Gordon的帮助。 –

+1

@IslamWazery。 。 。您的原始查询不处理这种情况。但很容易:'(count(distinct t.id)/ nullif(count(distinct m.id),0))'。 –

+0

谢谢你,我接受你的答案,因为它真的是我需要的。 –

2

你可以算出这样的方式为每个驱动程序的总人次及总比赛:

select driver_id, count(t.id) as total_trips, count(m.id) as total_matches 
from trips t 
left join matches m on (t.id = trip_id) 
group by 1 

使用该查询作为派生表与users加入:

select email, total_trips, total_matches, total_trips::dec/ nullif(total_matches, 0) result 
from users u 
left join (
    select driver_id, count(t.id) as total_trips, count(m.id) as total_matches 
    from trips t 
    left join matches m on (t.id = trip_id) 
    group by 1 
    ) s on u.id = driver_id 
order by 1; 

SQLFiddle.