SQL Server, inconsistency in result of DATEDIFF - sql

I'm trying to understand why the DATEDIFF does not work consistently.
I have a table Projects with below values:
Task_ID Start_Date End_Date
--------------------------------------
1 2015-10-01 2015-10-02
24 2015-10-02 2015-10-03
2 2015-10-03 2015-10-04
23 2015-10-04 2015-10-05
3 2015-10-11 2015-10-12
22 2015-10-12 2015-10-13
4 2015-10-15 2015-10-16
21 2015-10-17 2015-10-18
5 2015-10-19 2015-10-20
20 2015-10-21 2015-10-22
6 2015-10-25 2015-10-26
19 2015-10-26 2015-10-27
7 2015-10-27 2015-10-28
18 2015-10-28 2015-10-29
8 2015-10-29 2015-10-30
17 2015-10-30 2015-10-31
9 2015-11-01 2015-11-02
16 2015-11-04 2015-11-05
10 2015-11-07 2015-11-08
15 2015-11-06 2015-11-07
11 2015-11-05 2015-11-06
14 2015-11-11 2015-11-12
12 2015-11-12 2015-11-13
13 2015-11-17 2015-11-18
When I run the below query on it;
WITH t AS
(
SELECT
Start_Date s,
End_Date e,
ROW_NUMBER() OVER(ORDER BY Start_Date) rn
FROM
Projects
GROUP BY
Start_Date, End_Date
)
SELECT
s, e, rn, DATEDIFF(day, rn, s)
FROM t
I get this output:
2015-10-01 2015-10-02 1 42275
2015-10-02 2015-10-03 2 42275
2015-10-03 2015-10-04 3 42275
2015-10-04 2015-10-05 4 42275
2015-10-11 2015-10-12 5 42281
2015-10-12 2015-10-13 6 42281
2015-10-15 2015-10-16 7 42283
2015-10-17 2015-10-18 8 42284
2015-10-19 2015-10-20 9 42285
2015-10-21 2015-10-22 10 42286
2015-10-25 2015-10-26 11 42289
2015-10-26 2015-10-27 12 42289
2015-10-27 2015-10-28 13 42289
2015-10-28 2015-10-29 14 42289
2015-10-29 2015-10-30 15 42289
2015-10-30 2015-10-31 16 42289
2015-11-01 2015-11-02 17 42290
2015-11-04 2015-11-05 18 42292
2015-11-05 2015-11-06 19 42292
2015-11-06 2015-11-07 20 42292
2015-11-07 2015-11-08 21 42292
2015-11-11 2015-11-12 22 42295
2015-11-12 2015-11-13 23 42295
2015-11-17 2015-11-18 24 42299
But when I individually execute DATEDIFF, I get different results:
select DATEDIFF(day, 1, 2015-10-01)
2003
select DATEDIFF(day, 2, 2015-10-02)
2001
Can someone please explain this to me? Am I doing something wrong with the individual select statement?
Thanks for the help.

This is what the arguments for datediff look like.
DATEDIFF ( datepart , startdate , enddate )
Judging by the parameters you passed, I assume you are trying to substract 1 or 2 days from a date. You should use
DATEADD (datepart , number , date )
So substracting just becomes adding with a minus like DATEADD (day,-1,'2015-10-02')
If you really wanted to use the DATEDIFF function as intended, make sure you use single quotes around your dates and read the datepart boundaries section in the documentation, because a nanosecond difference at the boundary can turn into a year difference in your result.
Also when using a number X as a date, SQL Server interprets it as (1900-01-01 + X days).

Related

Replacement of values by logical condition by groups in SQL Server

Here's my sample data
shop_code product_id doc_date ship_count mark_1 outputer y
-----------------------------------------------------------------------------
1 00664НСК 11628 2015-01-03 00:00:00.000 12 1 8 1
2 00664НСК 11628 2015-01-05 00:00:00.000 7 1 8 1
3 00664НСК 11628 2015-01-06 00:00:00.000 24 0 8 1
4 00664НСК 11628 2015-01-07 00:00:00.000 18 1 8 1
5 00664НСК 11628 2015-01-08 00:00:00.000 12 1 8 1
6 00664НСК 11628 2015-01-09 00:00:00.000 18 0 8 1
7 00664НСК 11628 2015-01-10 00:00:00.000 6 0 6 1
8 00664НСК 11628 2015-01-11 00:00:00.000 6 1 6 1
9 00664НСК 11628 2015-01-12 00:00:00.000 6 1 6 1
10 00664НСК 11628 2015-01-13 00:00:00.000 18 1 12 0
11 00664НСК 11628 2015-01-14 00:00:00.000 6 1 6 0
12 00664НСК 11628 2015-01-15 00:00:00.000 18 1 12 0
13 00664НСК 11628 2015-01-16 00:00:00.000 12 1 12 1
14 00664НСК 11628 2015-01-17 00:00:00.000 18 1 12 1
15 00664НСК 11628 2015-01-18 00:00:00.000 12 1 12 1
16 00664НСК 11628 2015-01-19 00:00:00.000 10 1 10 0
17 00664НСК 11628 2015-01-20 00:00:00.000 24 1 12 0
18 00664НСК 11628 2015-01-21 00:00:00.000 6 1 6 0
19 00664НСК 11628 2015-01-24 00:00:00.000 6 1 6 0
20 00664НСК 11628 2015-01-25 00:00:00.000 6 0 6 0
21 00664НСК 11628 2015-01-26 00:00:00.000 10 0 10 1
22 00664НСК 11628 2015-01-27 00:00:00.000 6 1 6 0
23 00664НСК 11628 2015-01-28 00:00:00.000 10 1 10 0
24 00664НСК 11628 2015-01-29 00:00:00.000 70 0 12 1
25 00664НСК 11628 2015-01-30 00:00:00.000 100 1 12 1
Similar question I have asked for R and got working solution, but now I want do it using T-SQL.
I need observe such a condition: if y = 1 and mark1 = 1, then the output by mark1=1 must be replaced by the first value that goes for y = 0 and mark1 = 1 in the output variable.
If the first value that goes for Y = 0 and mark1 = 1 in the output is more than the ship_count, then in output left the actual value of ship_count
Zero category of mark1 for output, we don't touch.
This operation must be done by group ship_code+product_id
So the desired output should look like this:
shop_code product_id doc_date ship_count mark_1 outputer y
----------------------------------------------------------------------------
1 00664НСК 11628 2015-01-03 00:00:00.000 12 1 *12 1
2 00664НСК 11628 2015-01-05 00:00:00.000 7 1 *7 1
3 00664НСК 11628 2015-01-06 00:00:00.000 24 0 24 1
4 00664НСК 11628 2015-01-07 00:00:00.000 18 1 *12 1
5 00664НСК 11628 2015-01-08 00:00:00.000 12 1 *12 1
6 00664НСК 11628 2015-01-09 00:00:00.000 18 0 18 1
7 00664НСК 11628 2015-01-10 00:00:00.000 6 0 6 1
8 00664НСК 11628 2015-01-11 00:00:00.000 6 1 6 1
9 00664НСК 11628 2015-01-12 00:00:00.000 6 1 6 1
10 00664НСК 11628 2015-01-13 00:00:00.000 18 1 *12 0
11 00664НСК 11628 2015-01-14 00:00:00.000 6 1 6 0
12 00664НСК 11628 2015-01-15 00:00:00.000 18 1 12 0
13 00664НСК 11628 2015-01-16 00:00:00.000 12 1 *10 1
14 00664НСК 11628 2015-01-17 00:00:00.000 18 1 *10 1
15 00664НСК 11628 2015-01-18 00:00:00.000 12 1 *10 1
16 00664НСК 11628 2015-01-19 00:00:00.000 10 1 10 0
17 00664НСК 11628 2015-01-20 00:00:00.000 24 1 12 0
18 00664НСК 11628 2015-01-21 00:00:00.000 6 1 6 0
19 00664НСК 11628 2015-01-24 00:00:00.000 6 1 6 0
20 00664НСК 11628 2015-01-25 00:00:00.000 6 0 6 0
21 00664НСК 11628 2015-01-26 00:00:00.000 10 0 10 1
22 00664НСК 11628 2015-01-27 00:00:00.000 6 1 6 1
23 00664НСК 11628 2015-01-28 00:00:00.000 20 1 *12 0
24 00664НСК 11628 2015-01-29 00:00:00.000 70 1 12 0
25 00664НСК 11628 2015-01-30 00:00:00.000 100 1 12 1
Good evening,
You should use a case statement to do your job.
For finding the first value for the describing clauses , use a subquery in which you keep the order that you wish(order by) and select the top 1 value.
Give a try and if you face some issues ask again.

Sql data transformation

This is my source table
Reference ModifiedDate Teachers Students SchoolID ETC
-------------------------------------------------------------------------
1023175 2017-03-03 16:02:01.723 10 25 5
1023175 2017-03-07 07:59:49.283 15 50 15
1023175 2017-03-12 11:14:40.230 25 6 5
1023176 2017-03-04 16:02:01.723 11 35 8
1023176 2017-03-08 07:59:49.283 16 60 25
1023177 2017-03-15 11:14:40.230 15 7 2
I need the following output
Reference StartDate EndDate
---------------------------------------------
1023175 2017-03-03 16:02:01.723 2017-03-07 07:59:49.283
1023175 2017-03-07 07:59:49.283 2017-03-12 11:14:40.230
1023175 2017-03-12 11:14:40.230 9999-12-31 00:00:00.000
1023176 2017-03-04 16:02:01.723 2017-03-08 07:59:49.283
1023176 2017-03-08 07:59:49.283 9999-12-31 00:00:00.000
1023177 2017-03-15 11:14:40.230 9999-12-31 00:00:00.000 (last record should have this value)
Teachers Students SchoolID
10 25 5
15 50 15
25 6 5
11 35 8
16 60 25
15 7 2
All other columns like Teachers,Students and SchoolId etc also have to be in the output along with each record.
Any suggestions on how this can be achieved?
Using Sql Server 2008
using outer apply():
select
Reference
, StartDate = t.ModifiedDate
, EndDate = coalesce(x.ModifiedDate, convert(datetime,'9999-12-31 00:00:00.000'))
, Teachers
, Students
, SchoolID
from t
outer apply (
select top 1 i.ModifiedDate
from t as i
where i.Reference = t.Reference
and i.ModifiedDate > t.ModifiedDate
order by i.ModifiedDate asc
) x
rextester demo: http://rextester.com/RFTD32624
returns:
+-----------+-------------------------+-------------------------+----------+----------+----------+
| Reference | StartDate | EndDate | Teachers | Students | SchoolID |
+-----------+-------------------------+-------------------------+----------+----------+----------+
| 1023175 | 2017-03-03 16:02:01.723 | 2017-03-07 07:59:49.283 | 10 | 25 | 5 |
| 1023175 | 2017-03-07 07:59:49.283 | 2017-03-12 11:14:40.230 | 15 | 50 | 15 |
| 1023175 | 2017-03-12 11:14:40.230 | 9999-12-31 00:00:00.000 | 25 | 6 | 5 |
| 1023176 | 2017-03-04 16:02:01.723 | 2017-03-08 07:59:49.283 | 11 | 35 | 8 |
| 1023176 | 2017-03-08 07:59:49.283 | 9999-12-31 00:00:00.000 | 16 | 60 | 25 |
| 1023177 | 2017-03-15 11:14:40.230 | 9999-12-31 00:00:00.000 | 15 | 7 | 2 |
+-----------+-------------------------+-------------------------+----------+----------+----------+
Reference:
apply() - msdn
The power of T-SQL's APPLY operator - Rob Farley
APPLY: It Slices! It Dices! It Does It All! - Brad Shulz

How to get count incremental by date

I am trying to get a count of rows with incremental dates.
My table looks like this:
ID name status create_date
1 John AC 2016-01-01 00:00:26.513
2 Jane AC 2016-01-02 00:00:26.513
3 Kane AC 2016-01-02 00:00:26.513
4 Carl AC 2016-01-03 00:00:26.513
5 Dave AC 2016-01-04 00:00:26.513
6 Gina AC 2016-01-04 00:00:26.513
Now what I want to return from the SQL is something like this:
Date Count
2016-01-01 1
2016-01-02 3
2016-01-03 4
2016-01-04 6
You can make use of COUNT() OVER () without PARTITION BY,by using ORDER BY. It will give you the cumulative sum.Use DISTINCT to filter out the duplicate values.
SELECT DISTINCT CAST(create_date AS DATE) [Date],
COUNT(create_date) OVER (ORDER BY CAST(create_date AS DATE)) as [COUNT]
FROM [YourTable]
SELECT create_date, COUNT(create_date) as [COUNT]
FROM (
SELECT CAST(create_date AS DATE) create_date
FROM [YourTable]
) T
GROUP BY create_date
Per your description, you need a continuous dates list, Does it make sense?
This sample only generating one-month data.
CREATE TABLE #tt(ID INT, name VARCHAR(10), status VARCHAR(10), create_date DATETIME)
INSERT INTO #tt
SELECT 1,'John','AC','2016-01-01 00:00:26.513' UNION
SELECT 2,'Jane','AC','2016-01-02 00:00:26.513' UNION
SELECT 3,'Kane','AC','2016-01-02 00:00:26.513' UNION
SELECT 4,'Carl','AC','2016-01-03 00:00:26.513' UNION
SELECT 5,'Dave','AC','2016-01-04 00:00:26.513' UNION
SELECT 6,'Gina','AC','2016-01-04 00:00:26.513' UNION
SELECT 7,'Tina','AC','2016-01-08 00:00:26.513'
SELECT * FROM #tt
SELECT CONVERT(DATE,DATEADD(d,sv.number,n.FirstDate)) AS [Date],COUNT(n.num) AS [Count]
FROM master.dbo.spt_values AS sv
LEFT JOIN (
SELECT MIN(t.create_date)OVER() AS FirstDate,DATEDIFF(d,MIN(t.create_date)OVER(),t.create_date) AS num FROM #tt AS t
) AS n ON n.num<=sv.number
WHERE sv.type='P' AND sv.number>=0 AND MONTH(DATEADD(d,sv.number,n.FirstDate))=MONTH(n.FirstDate)
GROUP BY CONVERT(DATE,DATEADD(d,sv.number,n.FirstDate))
Date Count
---------- -----------
2016-01-01 1
2016-01-02 3
2016-01-03 4
2016-01-04 6
2016-01-05 6
2016-01-06 6
2016-01-07 6
2016-01-08 7
2016-01-09 7
2016-01-10 7
2016-01-11 7
2016-01-12 7
2016-01-13 7
2016-01-14 7
2016-01-15 7
2016-01-16 7
2016-01-17 7
2016-01-18 7
2016-01-19 7
2016-01-20 7
2016-01-21 7
2016-01-22 7
2016-01-23 7
2016-01-24 7
2016-01-25 7
2016-01-26 7
2016-01-27 7
2016-01-28 7
2016-01-29 7
2016-01-30 7
2016-01-31 7
2017-01-01 7
2017-01-02 7
2017-01-03 7
2017-01-04 7
2017-01-05 7
2017-01-06 7
2017-01-07 7
2017-01-08 7
2017-01-09 7
2017-01-10 7
2017-01-11 7
2017-01-12 7
2017-01-13 7
2017-01-14 7
2017-01-15 7
2017-01-16 7
2017-01-17 7
2017-01-18 7
2017-01-19 7
2017-01-20 7
2017-01-21 7
2017-01-22 7
2017-01-23 7
2017-01-24 7
2017-01-25 7
2017-01-26 7
2017-01-27 7
2017-01-28 7
2017-01-29 7
2017-01-30 7
2017-01-31 7
2018-01-01 7
2018-01-02 7
2018-01-03 7
2018-01-04 7
2018-01-05 7
2018-01-06 7
2018-01-07 7
2018-01-08 7
2018-01-09 7
2018-01-10 7
2018-01-11 7
2018-01-12 7
2018-01-13 7
2018-01-14 7
2018-01-15 7
2018-01-16 7
2018-01-17 7
2018-01-18 7
2018-01-19 7
2018-01-20 7
2018-01-21 7
2018-01-22 7
2018-01-23 7
2018-01-24 7
2018-01-25 7
2018-01-26 7
2018-01-27 7
2018-01-28 7
2018-01-29 7
2018-01-30 7
2018-01-31 7
2019-01-01 7
2019-01-02 7
2019-01-03 7
2019-01-04 7
2019-01-05 7
2019-01-06 7
2019-01-07 7
2019-01-08 7
2019-01-09 7
2019-01-10 7
2019-01-11 7
2019-01-12 7
2019-01-13 7
2019-01-14 7
2019-01-15 7
2019-01-16 7
2019-01-17 7
2019-01-18 7
2019-01-19 7
2019-01-20 7
2019-01-21 7
2019-01-22 7
2019-01-23 7
2019-01-24 7
2019-01-25 7
2019-01-26 7
2019-01-27 7
2019-01-28 7
2019-01-29 7
2019-01-30 7
2019-01-31 7
2020-01-01 7
2020-01-02 7
2020-01-03 7
2020-01-04 7
2020-01-05 7
2020-01-06 7
2020-01-07 7
2020-01-08 7
2020-01-09 7
2020-01-10 7
2020-01-11 7
2020-01-12 7
2020-01-13 7
2020-01-14 7
2020-01-15 7
2020-01-16 7
2020-01-17 7
2020-01-18 7
2020-01-19 7
2020-01-20 7
2020-01-21 7
2020-01-22 7
2020-01-23 7
2020-01-24 7
2020-01-25 7
2020-01-26 7
2020-01-27 7
2020-01-28 7
2020-01-29 7
2020-01-30 7
2020-01-31 7
2021-01-01 7
2021-01-02 7
2021-01-03 7
2021-01-04 7
2021-01-05 7
2021-01-06 7
2021-01-07 7
2021-01-08 7
2021-01-09 7
2021-01-10 7
2021-01-11 7
2021-01-12 7
2021-01-13 7
2021-01-14 7
2021-01-15 7
2021-01-16 7
2021-01-17 7
2021-01-18 7
2021-01-19 7
2021-01-20 7
2021-01-21 7
2021-01-22 7
2021-01-23 7
2021-01-24 7
2021-01-25 7
2021-01-26 7
2021-01-27 7
2021-01-28 7
2021-01-29 7
2021-01-30 7
2021-01-31 7
select r.date,count(r.date) count
from
(
select id,name,substring(convert(nvarchar(50),create_date),1,10) date
from tblName
) r
group by r.date
In this code, in the subquery part,
I select the first 10 letter of date which is converted from dateTime to nvarchar so I make like '2016-01-01'. (which is not also necessary but for make code more readable I prefer to do it in this way).
Then with a simple group by I have date and date's count.

Dates between two dates from a table

I can't find the specific answer to this question but apologies if it has been asked previously.
I have the following example table which I have kept simple but it contains more rows and Types. It gets updated frequently.
Type From To Qty
1 2016-01-01 00:00:00.0000000 2016-01-03 00:00:00.0000000 30
1 2016-01-04 00:00:00.0000000 2016-01-05 00:00:00.0000000 31
1 2016-01-06 00:00:00.0000000 NULL 31
2 2016-04-24 00:00:00.0000000 NULL 15
I want to be able to update a table every day (as shown below) so it shows all of the dates between (and including) the From and To dates. The Qty for the relevant date must be displayed up to todays date where the TO is NULL.
Type Date Qty
1 2016-01-01 00:00:00.0000000 30
1 2016-01-02 00:00:00.0000000 30
1 2016-01-03 00:00:00.0000000 30
1 2016-04-04 00:00:00.0000000 31
1 2016-04-05 00:00:00.0000000 31
1 2016-04-06 00:00:00.0000000 31
1 2016-04-07 00:00:00.0000000 31
1 .... up to today where TO is NULL
1 2016-07-25 00:00:00.0000000 31
2 2016-04-24 00:00:00.0000000 15
2 .... up to today where TO is NULL
2 2016-07-25 00:00:00.0000000 15
Thank you in advance for your help.
Using Numbers table..
Demo Here
select b.*,qty from #test
cross apply
(
select dateadd(day,n,fromdate) from
numbers
where n<=
case when todate is null
then datediff(day,fromdate,getdate()) else datediff(day,fromdate,todate) end
) b(upd)
You can do this using a recursive CTE to generate all of the dates and JOIN to that for the result:
Test Data
Create Table Test
(
[Type] Int,
[From] Date,
[To] Date,
Qty Int
)
Insert Test
Values
(1, '2016-01-01', '2016-01-03', 30 ),
(1, '2016-01-04', '2016-01-05', 31 ),
(1, '2016-01-06', NULL, 31 ),
(2, '2016-04-24', NULL, 15 )
Query
;With MinMax As
(
Select Min([From]) MinFrom,
Max([To]) MaxTo,
Convert(Date, GetDate()) Today
From Test
), Date (Date) As
(
Select MinFrom
From MinMax
Union All
Select DateAdd(Day, 1, Date)
From Date
Where Date < (Select MaxTo From MinMax)
Or Date < (Select Today From MinMax)
)
Select T.[Type],
D.[Date],
T.Qty
From Test T
Join Date D On D.Date Between T.[From] And Coalesce(T.[To], Convert(Date, GetDate()))
Order By T.[Type], D.[Date]
Option (MaxRecursion 0)
Results
Type Date Qty
1 2016-01-01 30
1 2016-01-02 30
1 2016-01-03 30
1 2016-01-04 31
1 2016-01-05 31
1 2016-01-06 31
1 2016-01-07 31
1 2016-01-08 31
1 2016-01-09 31
1 2016-01-10 31
1 2016-01-11 31
1 2016-01-12 31
1 2016-01-13 31
1 2016-01-14 31
1 2016-01-15 31
1 2016-01-16 31
1 2016-01-17 31
1 2016-01-18 31
1 2016-01-19 31
1 2016-01-20 31
1 2016-01-21 31
1 2016-01-22 31
1 2016-01-23 31
1 2016-01-24 31
1 2016-01-25 31
1 2016-01-26 31
1 2016-01-27 31
1 2016-01-28 31
1 2016-01-29 31
1 2016-01-30 31
1 2016-01-31 31
1 2016-02-01 31
1 2016-02-02 31
1 2016-02-03 31
1 2016-02-04 31
1 2016-02-05 31
1 2016-02-06 31
1 2016-02-07 31
1 2016-02-08 31
1 2016-02-09 31
1 2016-02-10 31
1 2016-02-11 31
1 2016-02-12 31
1 2016-02-13 31
1 2016-02-14 31
1 2016-02-15 31
1 2016-02-16 31
1 2016-02-17 31
1 2016-02-18 31
1 2016-02-19 31
1 2016-02-20 31
1 2016-02-21 31
1 2016-02-22 31
1 2016-02-23 31
1 2016-02-24 31
1 2016-02-25 31
1 2016-02-26 31
1 2016-02-27 31
1 2016-02-28 31
1 2016-02-29 31
1 2016-03-01 31
1 2016-03-02 31
1 2016-03-03 31
1 2016-03-04 31
1 2016-03-05 31
1 2016-03-06 31
1 2016-03-07 31
1 2016-03-08 31
1 2016-03-09 31
1 2016-03-10 31
1 2016-03-11 31
1 2016-03-12 31
1 2016-03-13 31
1 2016-03-14 31
1 2016-03-15 31
1 2016-03-16 31
1 2016-03-17 31
1 2016-03-18 31
1 2016-03-19 31
1 2016-03-20 31
1 2016-03-21 31
1 2016-03-22 31
1 2016-03-23 31
1 2016-03-24 31
1 2016-03-25 31
1 2016-03-26 31
1 2016-03-27 31
1 2016-03-28 31
1 2016-03-29 31
1 2016-03-30 31
1 2016-03-31 31
1 2016-04-01 31
1 2016-04-02 31
1 2016-04-03 31
1 2016-04-04 31
1 2016-04-05 31
1 2016-04-06 31
1 2016-04-07 31
1 2016-04-08 31
1 2016-04-09 31
1 2016-04-10 31
1 2016-04-11 31
1 2016-04-12 31
1 2016-04-13 31
1 2016-04-14 31
1 2016-04-15 31
1 2016-04-16 31
1 2016-04-17 31
1 2016-04-18 31
1 2016-04-19 31
1 2016-04-20 31
1 2016-04-21 31
1 2016-04-22 31
1 2016-04-23 31
1 2016-04-24 31
1 2016-04-25 31
1 2016-04-26 31
1 2016-04-27 31
1 2016-04-28 31
1 2016-04-29 31
1 2016-04-30 31
1 2016-05-01 31
1 2016-05-02 31
1 2016-05-03 31
1 2016-05-04 31
1 2016-05-05 31
1 2016-05-06 31
1 2016-05-07 31
1 2016-05-08 31
1 2016-05-09 31
1 2016-05-10 31
1 2016-05-11 31
1 2016-05-12 31
1 2016-05-13 31
1 2016-05-14 31
1 2016-05-15 31
1 2016-05-16 31
1 2016-05-17 31
1 2016-05-18 31
1 2016-05-19 31
1 2016-05-20 31
1 2016-05-21 31
1 2016-05-22 31
1 2016-05-23 31
1 2016-05-24 31
1 2016-05-25 31
1 2016-05-26 31
1 2016-05-27 31
1 2016-05-28 31
1 2016-05-29 31
1 2016-05-30 31
1 2016-05-31 31
1 2016-06-01 31
1 2016-06-02 31
1 2016-06-03 31
1 2016-06-04 31
1 2016-06-05 31
1 2016-06-06 31
1 2016-06-07 31
1 2016-06-08 31
1 2016-06-09 31
1 2016-06-10 31
1 2016-06-11 31
1 2016-06-12 31
1 2016-06-13 31
1 2016-06-14 31
1 2016-06-15 31
1 2016-06-16 31
1 2016-06-17 31
1 2016-06-18 31
1 2016-06-19 31
1 2016-06-20 31
1 2016-06-21 31
1 2016-06-22 31
1 2016-06-23 31
1 2016-06-24 31
1 2016-06-25 31
1 2016-06-26 31
1 2016-06-27 31
1 2016-06-28 31
1 2016-06-29 31
1 2016-06-30 31
1 2016-07-01 31
1 2016-07-02 31
1 2016-07-03 31
1 2016-07-04 31
1 2016-07-05 31
1 2016-07-06 31
1 2016-07-07 31
1 2016-07-08 31
1 2016-07-09 31
1 2016-07-10 31
1 2016-07-11 31
1 2016-07-12 31
1 2016-07-13 31
1 2016-07-14 31
1 2016-07-15 31
1 2016-07-16 31
1 2016-07-17 31
1 2016-07-18 31
1 2016-07-19 31
1 2016-07-20 31
1 2016-07-21 31
1 2016-07-22 31
1 2016-07-23 31
1 2016-07-24 31
1 2016-07-25 31
1 2016-07-26 31
2 2016-04-24 15
2 2016-04-25 15
2 2016-04-26 15
2 2016-04-27 15
2 2016-04-28 15
2 2016-04-29 15
2 2016-04-30 15
2 2016-05-01 15
2 2016-05-02 15
2 2016-05-03 15
2 2016-05-04 15
2 2016-05-05 15
2 2016-05-06 15
2 2016-05-07 15
2 2016-05-08 15
2 2016-05-09 15
2 2016-05-10 15
2 2016-05-11 15
2 2016-05-12 15
2 2016-05-13 15
2 2016-05-14 15
2 2016-05-15 15
2 2016-05-16 15
2 2016-05-17 15
2 2016-05-18 15
2 2016-05-19 15
2 2016-05-20 15
2 2016-05-21 15
2 2016-05-22 15
2 2016-05-23 15
2 2016-05-24 15
2 2016-05-25 15
2 2016-05-26 15
2 2016-05-27 15
2 2016-05-28 15
2 2016-05-29 15
2 2016-05-30 15
2 2016-05-31 15
2 2016-06-01 15
2 2016-06-02 15
2 2016-06-03 15
2 2016-06-04 15
2 2016-06-05 15
2 2016-06-06 15
2 2016-06-07 15
2 2016-06-08 15
2 2016-06-09 15
2 2016-06-10 15
2 2016-06-11 15
2 2016-06-12 15
2 2016-06-13 15
2 2016-06-14 15
2 2016-06-15 15
2 2016-06-16 15
2 2016-06-17 15
2 2016-06-18 15
2 2016-06-19 15
2 2016-06-20 15
2 2016-06-21 15
2 2016-06-22 15
2 2016-06-23 15
2 2016-06-24 15
2 2016-06-25 15
2 2016-06-26 15
2 2016-06-27 15
2 2016-06-28 15
2 2016-06-29 15
2 2016-06-30 15
2 2016-07-01 15
2 2016-07-02 15
2 2016-07-03 15
2 2016-07-04 15
2 2016-07-05 15
2 2016-07-06 15
2 2016-07-07 15
2 2016-07-08 15
2 2016-07-09 15
2 2016-07-10 15
2 2016-07-11 15
2 2016-07-12 15
2 2016-07-13 15
2 2016-07-14 15
2 2016-07-15 15
2 2016-07-16 15
2 2016-07-17 15
2 2016-07-18 15
2 2016-07-19 15
2 2016-07-20 15
2 2016-07-21 15
2 2016-07-22 15
2 2016-07-23 15
2 2016-07-24 15
2 2016-07-25 15
2 2016-07-26 15

How to add status to the table

I have the following table where is clipping from my db. I have 2 types of contracts.
I: client pays for first 6mth 60$, next 6mth 120$ (111 client)
II: client pays for first 6mth 60$ but if want still pays 60$ the contract will be extended at 6mth, whole contract is 18mth. (321 client who still pays)
ID_Client | Amount | Amount_charge | Lenght | Date_from | Date_to | Reverse
--------------------------------------------------------------------------------
111 60 60 12 2015-01-01 2015-01-31 12
111 60 60 12 2015-02-01 2015-02-28 11
111 60 60 12 2015-03-01 2015-03-31 10
111 60 60 12 2015-04-01 2015-04-30 9
111 60 60 12 2015-05-01 2015-05-31 8
111 60 60 12 2015-06-01 2015-06-30 7
111 120 60 12 2015-07-01 2015-07-31 6
111 120 60 12 2015-08-01 2015-08-31 5
111 120 60 12 2015-09-01 2015-09-30 4
111 120 60 12 2015-10-01 2015-10-31 3
111 120 60 12 2015-11-01 2015-11-30 2
111 120 60 12 2015-12-01 2015-12-31 1
111 120 60 12 2016-01-01 2015-01-31 0
111 120 60 12 2016-02-01 2015-02-29 0
321 60 60 12 2015-01-01 2015-01-31 12
321 60 60 12 2015-02-01 2015-02-28 11
321 60 60 12 2015-03-01 2015-03-31 10
321 60 60 12 2015-04-01 2015-04-30 9
321 60 60 12 2015-05-01 2015-05-31 8
321 60 60 12 2015-06-01 2015-06-30 7
321 60 60 12 2015-07-01 2015-07-31 6
321 60 60 12 2015-08-01 2015-08-31 5
321 60 60 12 2015-09-01 2015-09-30 4
321 60 60 12 2015-10-01 2015-10-31 3
321 60 60 12 2015-11-01 2015-11-30 2
321 60 60 12 2015-12-01 2015-12-31 1
321 60 60 12 2016-01-01 2016-01-30 0
321 60 60 12 2016-02-01 2016-02-31 0
321 60 60 12 2016-03-01 2016-03-30 0
321 60 60 12 2016-04-01 2016-04-31 0
I need to add status column.
A - normal period of agreement
D - where the agreement is doubled after 6mth but after 12mth is E(nd of agreemnt)
E - where contract is finished
L - where contract after 6mth was extended, after 18mth the status will be type E
For 321 Client after 12mth the lenght of contract was updated from 12 to 18
I have a lot of clients so i think better will be using loop to go by all clients?
ID_Client | Amount | Amount_charge | Lenght | Date_from | Date_to | Reverse | Status
-----------------------------------------------------------------------------------------
111 60 60 12 2015-01-01 2015-01-31 12 A
111 60 60 12 2015-02-01 2015-02-28 11 A
111 60 60 12 2015-03-01 2015-03-31 10 A
111 60 60 12 2015-04-01 2015-04-30 9 A
111 60 60 12 2015-05-01 2015-05-31 8 A
111 60 60 12 2015-06-01 2015-06-30 7 A
111 120 60 12 2015-07-01 2015-07-31 6 D
111 120 60 12 2015-08-01 2015-08-31 5 D
111 120 60 12 2015-09-01 2015-09-30 4 D
111 120 60 12 2015-10-01 2015-10-31 3 D
111 120 60 12 2015-11-01 2015-11-30 2 D
111 120 60 12 2015-12-01 2015-12-31 1 D
111 120 60 12 2016-01-01 2015-01-31 0 E
111 120 60 12 2016-02-01 2015-02-29 0 E
321 60 60 12 2015-01-01 2015-01-31 12 A
321 60 60 12 2015-02-01 2015-02-28 11 A
321 60 60 12 2015-03-01 2015-03-31 10 A
321 60 60 12 2015-04-01 2015-04-30 9 A
321 60 60 12 2015-05-01 2015-05-31 8 A
321 60 60 12 2015-06-01 2015-06-30 7 A
321 60 60 12 2015-07-01 2015-07-31 6 L
321 60 60 12 2015-08-01 2015-08-31 5 L
321 60 60 12 2015-09-01 2015-09-30 4 L
321 60 60 12 2015-10-01 2015-10-31 3 L
321 60 60 12 2015-11-01 2015-11-30 2 L
321 60 60 12 2015-12-01 2015-12-31 1 L
321 60 60 18 2016-01-01 2016-01-30 0 L
321 60 60 18 2016-02-01 2016-02-31 0 L
321 60 60 18 2016-03-01 2016-03-30 0 L
321 60 60 18 2016-04-01 2016-04-31 0 L
If the Reverse column is what I think:
update table1 a
set "Status"=
CASE
WHEN A."Reverse" > 6 THEN
'A'
WHEN A."Reverse" > 0 THEN
DECODE (A."Amount", A."Amount_charge", 'L', 'D')
ELSE
CASE
WHEN A."Amount" <> A."Amount_charge" THEN
'E'
ELSE
CASE WHEN ADD_MONTHS ( (SELECT b."Date_from" FROM table1 b WHERE a."ID_Client" = b."ID_Client" AND b."Reverse" = 1),6) > a."Date_from" THEN 'L'
ELSE
'E'
END
END
END
Better is to calculate the sums. The amount per month come from first payment. Something like this:
DECLARE
CURSOR c2
IS
SELECT ID_CLIENT, --AMOUNT, AMOUNT_CHARGE, LENGTH, DATE_FROM, DATE_TO, REVERSE, STATUS,
FIRST_VALUE (amount_charge) OVER (PARTITION BY id_client ORDER BY date_from) first_amount_charge,
SUM (amount) OVER (PARTITION BY id_client ORDER BY date_from) sum_amount,
SUM (amount_charge) OVER (PARTITION BY id_client ORDER BY date_from) sum_amount_charge
FROM TABLE2
FOR UPDATE NOWAIT;
BEGIN
FOR c1 IN c2
LOOP
UPDATE table2
SET status = CASE WHEN c1.sum_amount <= 6 * c1.first_amount_charge THEN 'A'
WHEN c1.sum_amount > 18 * c1.first_amount_charge THEN 'E'
WHEN c1.sum_amount > c1.sum_amount_charge THEN 'D'
ELSE 'L'
END
WHERE CURRENT OF c2;
END LOOP;
END;