簡體   English   中英

在SQL中每天進行計算

[英]Calculating per day in SQL

我有一個這樣的SQL表:

Id    Date     Price
1  21.09.09     25
2  31.08.09     16
1  23.09.09     21
2  03.09.09     12

因此,我需要的是獲取每個id和dif之間的最小和最大日期(以天為單位)。 這很容易。 使用SQLlite語法:

  SELECT id, 
         min(date), 
         max(date), 
         julianday(max(date)) - julianday(min(date)) as dif 
  from table group by id

然后是一個棘手的問題:在這個差異期內,我如何獲得每天的價格。 我的意思是這樣的:

ID Date      PricePerDay
1  21.09.09      25
1  22.09.09       0
1  23.09.09      21
2  31.08.09      16
2  01.09.09       0
2  02.09.09       0
2  03.09.09      12

我創建了一個cte,就像您提到的日歷一樣,但是不知道如何獲得期望的結果:

WITH RECURSIVE
cnt(x) AS (
 SELECT 0
 UNION ALL
 SELECT x+1 FROM cnt
  LIMIT (SELECT ((julianday('2015-12-31') - julianday('2015-01-01')) + 1)))
SELECT date(julianday('2015-01-01'), '+' || x || ' days') as date FROM cnt

ps如果將使用sqllite語法,那就太棒了!

您可以使用遞歸CTE計算最小日期和最大日期之間的所有天數。 剩下的只是left join和一些邏輯:

with recursive cte as (
      select t.id, min(date) as thedate, max(date) as maxdate
      from t
      group by id
      union all
      select cte.id, date(thedate, '+1 day') as thedate, cte.maxdate
      from cte
      where cte.thedate < cte.maxdate
     )
select cte.id, cte.date,
       coalesce(t.price, 0) as PricePerDay
from cte left join 
     t
     on cte.id = t.id and cte.thedate = t.date;

一種方法是使用計數表。
要建立日期列表並將其與表格一起使用。

首先將DD.MM.YY格式的日期戳更改為YYYY-MM-DD日期格式。
為了能夠在SQL中實際使用它們作為日期。
在最終選擇中,它們被格式化回DD.MM.YY格式。

首先是一些測試數據:

create table testtable (Id int, [Date] varchar(8), Price int);

insert into testtable (Id,[Date],Price) values (1,'21.09.09',25);
insert into testtable (Id,[Date],Price) values (1,'23.09.09',21);
insert into testtable (Id,[Date],Price) values (2,'31.08.09',16);
insert into testtable (Id,[Date],Price) values (2,'03.09.09',12);

SQL:

with Digits as (
   select 0 as n  
   union all select 1 
   union all select 2 
   union all select 3 
   union all select 4 
   union all select 5 
   union all select 6 
   union all select 7 
   union all select 8 
   union all select 9 
),
t as (
    select Id, 
    ('20'||substr([Date],7,2)||'-'||substr([Date],4,2)||'-'||substr([Date],1,2)) as [Date],
    Price
    from testtable
),
Dates as (
  select Id, date(MinDate,'+'||(d2.n*10+d1.n)||' days') as [Date]
  from (
    select Id, min([Date]) as MinDate, max([Date]) as MaxDate 
    from t 
    group by Id
  ) q
  join Digits d1 
  join Digits d2
  where date(MinDate,'+'||(d2.n*10+d1.n)||' days') <= MaxDate
)
select d.Id, 
(substr(d.[Date],9,2)||'.'||substr(d.[Date],6,2)||'.'||substr(d.[Date],3,2)) as [Date],  
coalesce(t.Price,0) as Price 
from Dates d
left join t on (d.Id = t.Id and d.[Date] = t.[Date])
order by d.Id, d.[Date];

下面的遞歸SQL完全受到Gordon Linoff的出色回答的啟發。
無論如何,遞歸SQL可能更有效。
(他應該為接受的答案得到15分)。
此版本的區別在於,日期戳首先被格式化為YYYY-MM-DD。

with t as (
    select Id, 
    ('20'||substr([Date],7,2)||'-'||substr([Date],4,2)||'-'||substr([Date],1,2)) as [Date],
    Price
    from testtable
),
cte as (
  select Id, min([Date]) as [Date], max([Date]) as MaxDate from t
  group by Id
  union all
  select Id, date([Date], '+1 day'), MaxDate from cte
  where [Date] < MaxDate
)
select cte.Id, 
(substr(cte.[Date],9,2)||'.'||substr(cte.[Date],6,2)||'.'||substr(cte.[Date],3,2)) as [Date], 
coalesce(t.Price, 0) as PricePerDay
from cte
left join t
  on (cte.Id = t.Id and cte.[Date] = t.[Date])
order by cte.Id, cte.[Date];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM