这是Linux 18.04。我打算在VS Code中执行SQL代码,以计算应向客人支付的住宿费用。我有3张桌子-预订,房间和发票
DECLARE @day NUMERIC, @price NUMERIC, @total NUMERIC, @resID NUMERIC
SELECT @resID = resID FROM Reservation GROUP BY resID;
WHILE @resID <= 10
BEGIN
SELECT @day = DATEDIFF(day, departure_date, arrival_date) FROM Reservation
SELECT @price = price_per_night FROM Room
SELECT @total = @day * @price;
UPDATE Invoice SET overall_price = @total;
SET @resID = @resID+1
END
SELECT * FROM Invoice;
例如,如果客人住了2天-(DATEDIFF(天,出发日期,到达日期), 那么它应该计算2天* price_per_night(房间表) 将值放在发票表的total_price列中
答案 0 :(得分:-1)
所以我们看到您有很多东西要学习。您现有的所有代码都可以替换为2条语句-更新和选择。您从循环和单行的角度来思考-这是传统编程语言的典型特征。在tsql中,您需要考虑集合。
您应该做的基本伪代码示例如下:
update dbo.Invoice set overall_price =
(select price_per_night * datediff(day, arrival_date, departure_date) from ....)
where ... ;
select ... from dbo.Invoice order by ...;
那不是工作代码。需要从许多方面进行调整。但是请注意,发票与客户和房间之间必须存在关系。这就是为什么需要DDL的原因。正如我评论的那样,您做出了许多对现实生活完全无效的假设。也许这是一个简单的培训练习-在提问时也应提及。这样做避免了很多额外的工作,这些工作描述了潜在的陷阱和复杂性并讨论了不需要的复杂性。
还有一些其他想法。术语“ overall_price”具有误导性。您的客户必须支付最终或全部金额。正如我前面提到的,这通常不只是房间费用。您是否考虑过当客户使用多个房间时会发生什么?您的目标是分别为每个房间开票吗?不同的房间可以有不同的价格。您是否考虑过税收和其他费用?最后,您实际上只想更新状态为“尚未完成”的发票。您不想更新旧发票-特别是已付款的发票。因此,您仍然需要考虑很多复杂性。
一个特定于代码的注释。你有这个:
SELECT @resID = resID FROM Reservation GROUP BY resID;
考虑一下该怎么做。显然,您可以并且确实希望它产生许多行。那么您认为它为变量分配了什么值?语言是否保证您期望的价值?它不是。分配的值将是所产生的一组的值,但不能保证将分配最低的值。这是一个常见且错误的假设。那么如何在tsql中正确表达目标呢?
set @resID = (select min(resID) from dbo.Reservation);
请注意您需要开始使用的一些最佳做法。首先,终止您的陈述。最终它将是必需的。接下来,使用SET而不是SELECT来分配变量。有一个很大的不同。最后,对表进行模式限定。所有这些都是最佳做法,您应该花一些时间来学习它们。
最后一个想法。如果确实需要循环,请使用游标。一般来说,循环(和游标)是有效,高效的tsql代码中很少需要的东西。如果您发现自己的代码中需要循环,那么该是时候退后一步,重新想象一下您的问题以及解决方案的最佳途径。