使用lag()来执行计算

时间:2012-11-11 17:11:02

标签: oracle plsql

我需要帮助根据每个月的当前值来计算米的消耗量

我有以下表格:

地址(PostCode int,Street varchar)
Meter(MeterID int,InstallationDate date,PostCode int)
读(ReadNo int,ReadDate date,ReadValue int,MeterID int,ReaderID int)

我尝试了以下内容:

Select ReadDate, 
       ReadValue AS CurrentValue, 
       lag(readvalue, 1, 0) OVER (ORDER BY READVALUE) AS PreviousValue, 
       readvalue - lag(readvalue, 1, 0) OVER (ORDER BY READVALUE) AS Consumption
 From Reading R, 
      Meter M, 
      Address A 
Where R.MeterID = M.MeterID
  AND A.PostCode = M.PostCode AND A.PostCode = '1005'
Order By ReadDate;

当新仪表替换地址仪表时出现问题,有人可以帮我吗?

2 个答案:

答案 0 :(得分:1)

我相信很多人都会感谢你!

通过在LAG中使用ORDER BY READVALUE,您计算的是下一个最高(默认排序顺序是升序),而不是最后一个。这应该是

lag(readvalue, 1, 0) over (order by readdate desc)

获取先前读取的值。

您的地址表中没有足够的信息来确定仪表是否在同一地址。没有建筑物编号等。因此,您的问题的正确答案是社交的,与数据库无关。如果有人有两米发出两张账单。

但是,假设地址表 具有足够的信息以便能够唯一地识别地址,即每个邮政编码是单个建筑物,那么你已经做了正确的事情,尽管我会按如下方式重新组织您的查询(并停止引用整数)。

select r.readdate
     , r.readvalue - lag(r.readvalue, 1, 0) over ( order by readdate desc )
  from address a
  join meter m 
    on a.postcode = m.postcode
  join reading r
    on m.meterid = r.meterid
 where a.postcode = 1005
 order by readdate desc

您正在选择邮政编码的每个米,然后选择所有这些米的每个读数。如果在读数之间安装了新仪表,那你就没事了。

这似乎不太可行;应该有前一米的最终读数,否则readvalue将高于该值的滞后,这将使您回到两个账单场景。或者,您需要一种方法来显示账单中的账单何时“最终”。

要获取最新值,只需将其全部包含在子选择中并选择顶行:

select * from ( <above query> ) where rownum < 2

答案 1 :(得分:0)

您的架构是否与计量表(服务)无关?如果您使用的是商业客户信息系统,他们都会这样做并要求使用它来生成账单。有一个服务表,每个服务住在一个场所。邮寄地址可能与场所相同或不同。邮寄地址与客户相关联,例如:餐馆连锁店有一个主办公室和20个餐厅。他们在总公司收到账单,所以所有邮寄地址都是一样的,服务的20个物理地址可能非常不同。

如果您为此推出了自己的架构,则需要考虑实用程序计费的实际工作方式。 即使这只是一个玩具模型。

过去30年来,我在许多系统上都做到了这一点。他们都像上面那样工作。