有没有办法用 case 函数显示负值?

Posted

技术标签:

【中文标题】有没有办法用 case 函数显示负值?【英文标题】:Is there a way to display negative values with the case function? 【发布时间】:2020-06-14 07:02:15 【问题描述】:

问题:

提供一份报告,显示客户的全名(名字和姓氏一起)、山寨名称、山寨的地区名称、预订日期(格式为 2017 年 12 月 15 日)、预订价格、以及该小屋的预订价格与所有小屋的平均预订价格之间的差额(以 $yy.y 格式,例如 $25.6 格式,截断到最接近的小数点后 1 位),按全名降序排列。

我的回答:

SELECT CONCAT(Customer_FName," ",Customer_LName) AS 'Name', Cottage_Name, Region_Name, 
DATE_FORMAT(Booking_Date,"%D %M %Y" ) AS 'Date Booked', Booking_Price,
CASE 
    WHEN AVG(Booking_Price) < Booking_Price THEN Booking_Price - AVG(Booking_Price)
    ELSE -1 * (AVG(Booking_Price) - Booking_Price)
END AS 'Diff From Average'

FROM Customer

JOIN Booking USING(Customer_ID)
JOIN Cottage
JOIN Region
GROUP BY Name;

我的输出:

所需的输出必须显示负值而不是 0

我的问题:有谁知道可以与CASE... WHEN 执行相同操作并显示负值的函数?

SQLFiddle(包含数据和所有必要的文件):http://sqlfiddle.com/#!9/8a40db/2/0

ERD:

问题提示:

【问题讨论】:

【参考方案1】:

只有零,因为平均值与预订价格相同

但是根本不需要你的理由

您最好使用正确的连接和 ON clqause

SELECT 
    CONCAT(Customer_FName," ",Customer_LName) AS 'Name'
    , Cottage_Name
     , Region_Name, 
     DATE_FORMAT(Booking_Date,"%D %M %Y" ) AS 'Date Booked'
    , Booking_Price
    ,
    CONCAT('$',ROUND((Booking_Price - AVG(Booking_Price)),1)) AS 'Diff From Average'
FROM Customer
    JOIN Booking USING(Customer_ID)
    JOIN Cottage
   JOIN Region
GROUP BY Name;



Name            Cottage_Name                        Region_Name     Date Booked         Booking_Price   Diff From Average
Bob Perkins     Atlantic Beach Resort Cottage 1     Halifax         10th January 2018   144             $0.0
Charlie Oscar   Atlantic Beach Resort Cottage 1     Halifax         15th January 2018   1176            $294.0
Eve Evenfield   Atlantic Beach Resort Cottage 1     Halifax         22nd December 2017  654             $0.0
Frank Mitchell  Atlantic Beach Resort Cottage 1     Halifax         15th January 2018   384             $0.0
Grace Damon     Atlantic Beach Resort Cottage 1     Halifax         1st January 2018    170             $0.0
Student DalFCS  Atlantic Beach Resort Cottage 1     Halifax         15th January 2018   584             $154.5

【讨论】:

问题是“所有别墅的平均预订价格”我有点困惑,因为问题暗示我将发布为 edit1 我解决问题的技巧是编写一些适用于某些列的内容,然后一点一点地实现一些代码。 我改变了它适合这个问题。我删除了平均值,因为我添加了它来证明答案。现在 ot 显示美元符号并将结果四舍五入到 1 位。【参考方案2】:

您的查询未正确聚合g,尽管 mysql 对它的编译不够宽松。

如果您运行的是 MySQL 8.0,您可以使用窗口函数来实现:

select
    concat(c.Customer_FName, ' ', c.Customer_LName) AS Name, 
    b.Cottage_Name, 
    r.Region_Name, 
    DATE_FORMAT(Booking_Date,"%D %M %Y" ) AS Date_Booked, 
    b.Booking_Price,
    AVG(b.Booking_Price) OVER() - Booking_Price diff_from_average
from customer c
inner join booking b using(customer_id)
inner join region r using(??)

在早期版本中,您可以使用聚合查询来计算总体平均值:

select
    concat(c.Customer_FName, ' ', c.Customer_LName) AS Name, 
    b.Cottage_Name, 
    r.Region_Name, 
    date_format(Booking_Date,"%D %M %Y" ) AS Date_Booked, 
    b.Booking_Price,
    a.avg_booking_Price - Booking_Price diff_from_average
from customer c
inner join booking b using(customer_id)
inner join region r using(??)
cross join (select avg(booking_price) avg_booking_price from booking) a

旁注:

我添加了表别名并尝试在列前加上相关表 - 您可能需要查看

您在region 上缺少连接条件

【讨论】:

这种问题需要别名吗?为什么 Region 上的 join 需要条件? 只要查询中涉及多个表,别名就很有用 - 为列添加前缀可以明确它们来自哪个表(并避免名称冲突)。至于region:你需要一个反映bookingregion之间关系的连接条件,否则你会得到两个表行的笛卡尔积。

以上是关于有没有办法用 case 函数显示负值?的主要内容,如果未能解决你的问题,请参考以下文章

有啥办法可以防止 input type="number" 得到负值?

有没有办法在没有 CASE 表达式的情况下做到这一点?

解决 ODE 时避免负值

python用字典实现switch..case类似的函数调用

SQL Server 2016 - 有没有办法通过使用 CASE 来做类似于 PIVOT 的事情?

JPA:在 where 子句和 Case 语句中一起使用列表 - 有没有办法循环?