有没有办法用 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
:你需要一个反映booking
和region
之间关系的连接条件,否则你会得到两个表行的笛卡尔积。以上是关于有没有办法用 case 函数显示负值?的主要内容,如果未能解决你的问题,请参考以下文章
有啥办法可以防止 input type="number" 得到负值?
python用字典实现switch..case类似的函数调用