Home > Software design >  MySQL - multiple conditions
MySQL - multiple conditions

Time:11-07

I have two tables: orders, shops.

shops:

shop_id | name 
-----------------------
20      | PizzaShop
34      | SushiShop

orders:

orders_id | creation_time       | user_id | shop_id | Status
------------------------------------------------------------------
1         | 2021-01-01 14:00:00 | 1       | 20      | OK
2         | 2021-02-01 14:00:00 | 1       | 34      | Cancelled
3         | 2021-03-01 14:00:00 | 1       | 20      | OK
4         | 2021-04-01 14:00:00 | 1       | 34      | OK
5         | 2021-05-01 14:00:00 | 2       | 20      | OK
6         | 2021-06-01 14:00:00 | 2       | 20      | OK
7         | 2021-07-01 14:00:00 | 2       | 34      | OK
8         | 2021-08-01 14:00:00 | 2       | 34      | OK

I need to find the "favourite" shop of every user, knowing that the favourite is the one that has more "OK" orders, and if there are two shops with the same amount of orders, then select the one that has the most recent order.

The result should be something like this:

user_id | total_number_OK_orders | favourite_shop_name 
------------------------------------------------------------------
1       | 3                      | PizzaShop
2       | 4                      | SushiShop

I have no idea how to do the second column. For the first this is what I have for the moment:

SELECT 
    orders.user_id,
    SUM(if(orders.Status = 'OK', 1, 0)) AS total_number_OK_orders
FROM orders
LEFT JOIN shops
    ON orders.shop_id = shops.shop_id
GROUP BY orders.user_id;

CodePudding user response:

For MySql 8.0 you can use window functions SUM() and FIRST_VALUE():

SELECT DISTINCT o.user_id, 
       SUM(SUM(o.Status = 'OK')) OVER (PARTITION BY o.user_id) total_number_OK_orders,
       FIRST_VALUE(s.name) OVER (PARTITION BY o.user_id ORDER BY SUM(o.Status = 'OK') DESC, MAX(o.creation_time) DESC) favourite_shop_name 
FROM orders o LEFT JOIN shops s
ON s.shop_id = o.shop_id AND o.Status = 'OK'
GROUP BY o.user_id, s.shop_id;

See the demo.

CodePudding user response:

For MySQL 5.7 or earlier

SELECT a.user_id, COUNT(*) total_orders, 
  (
    SELECT MAX(s.name)
    FROM orders t
    JOIN shops s ON t.shop_id = s.shop_id
    WHERE t.user_id = a.user_id AND t.Status = 'OK'
    GROUP BY t.user_id, t.shop_id
    ORDER BY COUNT(*) DESC, MAX(t.creation_time) DESC
    LIMIT 1
  ) favorite_shop
FROM orders a 
LEFT JOIN shops b ON a.shop_id = b.shop_id
WHERE a.Status = 'OK'
GROUP BY a.user_id
  • Related