【问题标题】:How to using calculation of an aggregate function as filter criteria如何使用聚合函数的计算作为过滤条件
【发布时间】:2021-03-17 04:16:06
【问题描述】:

我有关于预订订单的表格

Bookings (booking_id, booking_time, driver_id, customer_id)
Drivers (driver_id, name)

我需要确定在过去 30 天内至少有一半预订由同一司机完成的所有客户。

解释

  • 客户 x 有 12 个预订,其中 7 个由 driver_01 完成。

  • 客户 y 有 10 个预订,其中 4 个由 driver_02 完成。

  • 客户 z 有 3 个预订,其中 3 个由 driver_03 完成

输出将返回 driver_01 和 driver_03 以及 booking_id

我尝试过使用自联接和计数聚合,但我仍然不明白逻辑

【问题讨论】:

    标签: mysql sql count subquery inner-join


    【解决方案1】:

    你可以用窗口函数来做:

    select b.*, d.name as driver_name
    from driver d
    inner join (
        select b.*, 
            count(*) over(partition by driver_id, customer_id) / count(*) over(partition by customer_id) as driver_ratio
        from booking b
    ) b on b.driver_id = d.driver_id
    where driver_ratio >= 0.6
    

    【讨论】:

    • @user14767369 。 . .我认为这是更好的解决方案,无论是在简单性还是性能方面。
    • 是的,我想是的,我以前从未使用过分区和计数,仍在寻找此功能的参考。谢谢!
    【解决方案2】:

    您正确地确定加入有助于获取每位客户的预订总数,因此

    DROP TABLE IF EXISTS BOOKINGS,drivers;
    
    create table Bookings (booking_id int, driver_id int, customer_id varchar(3));
    
    create table Drivers (driver_id int, name varchar(3));
    
    insert into bookings values
    (1,1,1),(2,1,1),(3,2,1),(4,2,1),(5,3,1),
    (6,1,2),(7,2,1);
    
    insert into drivers values
    (1,'aaa'),(2,'bbb');
    
    select b.driver_id,d.name,b.customer_id,count(*) bcount,scount, count(*) / scount * 100 percent
    from bookings b
    join (select customer_id,count(*) scount from bookings group by customer_id) s
            on s.customer_id = b.customer_id
    join  drivers d on d.driver_id = b.driver_id
    group by driver_id,d.name,customer_id having count(*) / scount * 100 >= 50;
    
    +-----------+------+-------------+--------+--------+----------+
    | driver_id | name | customer_id | bcount | scount | percent  |
    +-----------+------+-------------+--------+--------+----------+
    |         1 | aaa  | 2           |      1 |      1 | 100.0000 |
    |         2 | bbb  | 1           |      3 |      6 |  50.0000 |
    +-----------+------+-------------+--------+--------+----------+
    2 rows in set (0.002 sec)
    

    测试 50% 比测试 60% 更容易 - 不要忘记根据您的要求进行更改。

    【讨论】:

    • 太棒了,所以要生成 order_id,我可以将其用作子查询来自行加入 driver_id 和 customer_id。非常感谢
    【解决方案3】:

    我已经测试了@P.Salmon 的代码,因为我也有类似的方法,我发现@P.Salmon 的答案是正确的,但是如果你通过日期说例如你只想返回最后 30像你在你的问题上指定的日子,它可能不起作用

    见下文

    SELECT b.booking_date,b.driver_id, d.name, b.customer_id, COUNT(*) b_count, c_count, COUNT(*) / c_count * 100 percent
    FROM bookings b 
    JOIN (SELECT customer_id, COUNT(*) c_count from bookings GROUP BY customer_id) c ON c.customer_id = b.customer_id 
    JOIN drivers d ON d.driver_id = b.driver_id 
    WHERE b.booking_date BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
    GROUP BY booking_date, driver_id, d.name, customer_id 
    HAVING COUNT(*) / c_count * 100 >= 50;
    

    【讨论】:

      猜你喜欢
      • 2019-12-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      相关资源
      最近更新 更多