SQL查询1折扣表中的多重折扣

时间:2019-11-23 14:02:26

标签: mysql sql-order-by

我有一个数据表,如下所示:

---reservation_discount-----
id relation_id     title           rate
1  2               25% Discount    25
2  2               5% Discount     5
---reservation_hotel-----
id    room_id     price
2     1           2430

我的查询:

SELECT
reservation.customer,
hotel.title,
reservation_hotel.price,
reservation_discount.rate,
reservation_hotel.price * (100 - sum(reservation_discount.rate)) / 100 as total 
FROM
reservation_hotel
INNER JOIN reservation ON reservation_hotel.reservation_id = reservation.id
INNER JOIN hotel ON reservation_hotel.hotel_id = hotel.id
INNER JOIN room ON reservation_hotel.room_id = room.id AND room.hotel_id = hotel.id
INNER JOIN reservation_discount ON reservation_discount.relation_id = reservation_hotel.id
WHERE reservation_hotel.id=1 

我的问题是: 我希望他按顺序进行折扣,但是他没有得到25%5%,他得到了30%

如何按顺序应用折扣?

Price: 2430 - 25% = 1822,51822,5 - 5% = 1731.375

2 个答案:

答案 0 :(得分:1)

作为一种更复杂的算法,它可以具有您想给的尽可能多的折扣,您每次也可以选择单个折扣。

在此示例中,我同时拥有了Reservation_hotel.id,但是您只能使用1甚至全部。在此选择查询中,reservation_hotel.id称为rh.id

此选择语句

SELECT
  MIN(customer) customer,
  MIN(title) titke,
  MIN(price) price ,
  MIN(totalrate * 100) rate,
  MIN(total) total
FROM
  (SELECT
    rh.id id,
    r.customer customer,
    h.title title,
    rh.price price,
    rd.rate rate,
    if (@res = rh.id,@total :=@total,@total :=0) disc,
    if (@res = rh.id,@rate :=@rate,@rate :=0) disc2,
    if (@rate = 0, @rate := (100 - rd.rate)/ 100,@rate := @rate * (100 - rd.rate)/ 100) totalrate,
    if (@total=0,@total := rh.price * (100 - rd.rate) / 100,@total := @total * (100 - rd.rate) / 100) total,
    @res := rh.id        
  FROM
    reservation_hotel rh
    INNER JOIN reservation r ON rh.reservation_id = r.id
    INNER JOIN hotel h ON rh.hotel_id = h.id
    INNER JOIN room ro ON rh.room_id = ro.id AND ro.hotel_id = h.id
    INNER JOIN reservation_discount rd ON rd.relation_id = rh.id
    ,(SELECT @res := 0) r1,(SELECT @total := 0) r2,(SELECT @rate := 0) r3
  WHERE rh.id=1 or rh.id=2
  ORDER BY rh.id ) t1
GROUP BY id
ORDER BY id;

为您提供以下结果:

customer | titke         | price |  rate |    total
:------- | :------------ | ----: | ----: | -------:
John Doe | Premium Hotel |  2430 | 71.25 | 1731.375
John Doe | Premium Hotel |  2250 | 71.25 | 1603.125

DBfiddle示例https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=276a5474b1329d018ffacdc910ea5f10

它计算出正确的客户实际利率和总金额。

答案 1 :(得分:1)

要以通用的方式解决此问题,您需要某种递归。如果运行的是MySQL 8.0,则可以使用递归公用表表达式。

这个想法是首先将reservation_hotelreservation_discount中具有最小id的记录结合起来(使用相关子查询),然后应用该第一折扣。然后,我们获得下一个折扣,并将其应用于先前计算的价格。

此查询为您提供了逐步计算:

with recursive cte as (
    select r.*, r.price * (100 - d.rate) / 100 final_price, d.id discount_id
    from reservation_hotel r
    inner join reservation_discount d on d.id = (
        select min(d1.id) from reservation_discount d1 where d1.relation_id = r.id
    )
    union all
    select c.id, c.room_id, c.price, c.final_price * (100 - d.rate) / 100, d.id
    from cte c
    inner join reservation_discount d on d.id = (
        select min(d1.id) 
        from reservation_discount d1 
        where d1.relation_id = c.id and d1.id > c.discount_id
    )
)
select * from cte order by discount_id
id | room_id | price | final_price | discount_id
-: | ------: | ----: | ----------: | ----------:
 2 |       1 |  2430 |   1822.5000 |           1
 2 |       1 |  2430 |   1731.3750 |           2

如果您只想要最终价格,则可以使用汇总:

with recursive cte as (
    select r.*, r.price * (100 - d.rate) / 100 final_price, d.id discount_id
    from reservation_hotel r
    inner join reservation_discount d on d.id = (
        select min(d1.id) 
        from reservation_discount d1 
        where d1.relation_id = r.id
    )
    union all
    select c.id, c.room_id, c.price, c.final_price * (100 - d.rate) / 100, d.id
    from cte c
    inner join reservation_discount d on d.id = (
        select min(d1.id) 
        from reservation_discount d1 
        where d1.relation_id = c.id and d1.id > c.discount_id
    )
)
select id, room_id, price, min(final_price) final_price
from cte
group by id, room_id, price
id | room_id | price | final_price
-: | ------: | ----: | ----------:
 2 |       1 |  2430 |   1731.3750

Demo on DB Fiddle