Date Difference between consecutive rows adding additional columns - sql

Say I added a Cost Difference column to the second table from Rishal (see the below link for this previous post), how would I also calculate and display that?
Using just the 1001 Account Number and adding the following amounts of ID1=$10, ID4=$33 and ID6=$50 to the first table, how would I display in Rishal's second table a result of $23 and $17 in addition to the other 3 columns that are already there?
I've used this code (from GarethD) and would like to insert my Cost Difference column within this...Thanks in advance,
SELECT ID,
AccountNumber,
Date,
NextDate,
DATEDIFF("D", Date, NextDate)
FROM ( SELECT ID,
AccountNumber,
Date,
( SELECT MIN(Date)
FROM YourTable T2
WHERE T2.Accountnumber = T1.AccountNumber
AND T2.Date > T1.Date
) AS NextDate
FROM YourTable T1
) AS T
Date Difference between consecutive rows

I would recommend using JOIN to bring in the entire next record:
SELECT T.*, DATEDIFF("D", t.Date, t.NextDate) as datediff,
TNext.Amount, (Tnext.Amount - T.Amount) as amountdiff
FROM (SELECT T1.*,
(SELECT MIN(Date)
FROM YourTable T2
WHERE T2.Accountnumber = T1.AccountNumber AND
T2.Date > T1.Date
) AS NextDate
FROM YourTable as T1
) AS T LEFT JOIN
YourTable as Tnext
ON t.Accountnumber = tnext.Accountnumber AND t.Date = tnext.Accountnumber;

Related

Filter SQL Server Records by Latest Date on Every Year

How would I filter this SQL server database so only the green records are left aka the last recorded date every year for each Customer ID field.
If you want to get the rows, not only the date values, using ROW_NUMBER() is an option (you only need to use the appropriate PARTITON BY and ORDER BY clauses):
SELECT *
FROM (
SELECT
CustomerId,
[Date],
ROW_NUMBER() OVER (PARTITION BY CustomerId, YEAR[Date] ORDER BY [Date] DESC) AS Rn
FROM YourTable
) t
WHERE Rn = 1
To check the maximum date in the year, you can write a query to get for each year the date where not exists another (in the same year), as follow:
SELECT *
FROM yourtable t1
WHERE NOT EXISTS
(SELECT 1
FROM yourtable t2
WHERE t1.customerID = t2.customerID
AND t1.date > t2.date
AND DATEPART(YEAR, t1) = DATEPART(YEAR, t2))
If you have only two columns, then you can just use aggregation:
select customer_id, max(date)
from t
group by customer_id, year(date);

Query needed to show data in a different way

After making a query, I get this data in this format:
I need to set up a query that pairs dates related to same id and counts the difference in days.
the result should be like this:
I'm using postgresql. Could you please help me to set up the query to get the desired output ?
Thanks in advance
Hmmm . . . I'm thinking lead() and some additional filtering and arithmetic:
select id, date as date_start, next_date as date_end,
(next_date - date_start) as days
from (select t.*, lead(date) over (partition by id order by date) as next_date
from t
) t
where event = 0;
The most robust and maintainable answer is that by #GordonLinoff.
Another method to solve this can be using CTEs. Here I am assuming that event = 0 and event = 1 are paired (which is true in the example shown):
WITH t1 AS
(SELECT id, date
FROM t
WHERE event = 0 rank() OVER (
ORDER BY id, date) AS id_date_rank),
t2 AS
(SELECT id, date
FROM t
WHERE event = 1 rank() OVER (
ORDER BY id, date) AS id_date_rank),
SELECT t1.id,
t1.date AS date_start,
t2.date AS date_end,
DATE_PART('day', (t2.date - t1.date)) AS no_days
FROM t1
INNER JOIN t2 ON (t1.id_date_rank = t2.id_date_rank)
ORDER BY t1.id,
t1.date;

Access SQL Statement Calculate the Difference From Previous Month [duplicate]

This question already has answers here:
Query for getting value from another record in same table and filter by difference greater than a gap threshold
(2 answers)
Closed 3 years ago.
I'm using Microsoft Access 2016 to developing a new program, each month the data entry enter in a row the date, the total budget plan and cumulative expending amount. I am trying to create a query showing the monthly bases experiences. For example in this month August, the cumulative value 170000, the cumulative value for July 125000, so I need a query showing the difference is 45000.
Attached an Access file for short data examples.
https://www.dropbox.com/s/h9vlp84fzmjc93d/Minus%20Calculation.accdb?dl=0
Thanks for your support in advance!
Best Regards
Mahmoud
Assuming that you always want to see the data from exactly one month previous (whether or not such data exists), and that the data could be entered on any day in the month, you might consider the following:
select
t1.date,
t1.cumulative_expending_amount,
t2.cumulative_expending_amount,
t1.cumulative_expending_amount-t2.cumulative_expending_amount
from
YourTable t1 left join YourTable t2 on
t1.date >= dateserial(year(t2.date),month(t2.date)+1,1) and
t1.date <= dateserial(year(t2.date),month(t2.date)+2,0)
Change YourTable, date, and cumulative_expending_amount to suit the name of your table and fields respectively.
Following your comments, it would appear that the following SQL satisfies your requirements:
select
t1.itemid,
t1.date,
t1.cumulative_expending_amount,
(
select top 1 t3.cumulative_expending_amount
from YourTable t3
where t3.itemid = t1.itemid and t3.date < t1.date
order by t3.date desc
) as last_cumulative_expending_amount,
t1.cumulative_expending_amount-last_cumulative_expending_amount as diff
from
YourTable t1 inner join
(
select t.itemid, max(t.date) as mdate
from YourTable t
group by t.itemid
) t2 on t1.itemid = t2.itemid and t1.date = t2.mdate
order by
t1.itemid,
t1.date desc
You can use a correlated subquery. Based on your description, the code looks like this:
select t.*,
(select top (1) t2.cumulative_spending
from t as t2
where t2.date < t.date
order by t2.date desc
) as prev_cumulative_spending
from t;

Calculating AVG for NULL values from all previous rows

I have a table with 4 columns like this: EmployeeID, Date, StartTime, EndTime. First two columns are not nullable, but others 2 are.
I want to generate a report and fill the missing StartTime and EndTime with AVG value of the previous rows. I'm using the following statement for the StartTime column:
ISNULL([StartTime], DATEADD(SECOND, AVG([dbo].[GetTimeInSecondsFromDateTime]([StartTime])) OVER (PARTITION BY [EmployeeID] ORDER BY [Date]), [Date]))
The problem is, when i have 2 NULL values one after another, they get the same value (AVG from all the previous ones) and what i need is: in the calculation for the second NULL value, the previous one to be included too (which is calculated) ... the thing is, i have no idea how to implement it.
The query is not tested. I Hope it helps
Because of the null values, I suggest you to first Update By StartTime
UPDATE t1
SET StartTime = ISNULL(StartTime, t2.AvgStartTime)
FROM yourTable t1
JOIN (
SELECT
EmployeeID,
Date,
Avg(StartTime) OVER(ORDER BY Date Asc) As AvgStartTime,
FROM yourTAble
) t2 ON t1.EmployeeID = t2.EmployeeID
Where
t1.StartTime is null
then for endTime
UPDATE t1
SET EndTime = ISNULL(EndTime, t2.AvgEndTime)
FROM yourTable t1
JOIN (
SELECT
EmployeeID,
Date,
Avg(EndTime) OVER(ORDER BY Date Asc) As AvgEndTime,
FROM yourTAble
) t2 ON t1.EmployeeID = t2.EmployeeID
Where
t1.EndTime is null

How to show a row for the dates not in records of a table as zero

I am trying to show the records as zero for the dates not found.
Below is my basic query:
Select date_col, count(distinct file_col), count(*) from tab1
where date_col between 'date1' and 'date2'
group by date_col;
The output is for one date.
I want all the dates to be shown in result.
The general way to deal with this type of problem is to use something called a calendar table. This calendar table contains all the dates which you want to appear in your report. We can create a crude one by using a subquery:
SELECT
t1.date,
COUNT(DISTINCT t2.file_col) AS d_cnt,
COUNT(t2.file_col) AS cnt
FROM
(
SELECT '2018-06-01' AS date UNION ALL
SELECT '2018-06-02' UNION ALL
...
) t1
LEFT JOIN tab1 t2
ON t1.date = t2.date_col
WHERE
t1.date BETWEEN 'date1' and 'date2'
GROUP BY
t1.date;
Critical here is that we left join the calendar table to your table containing the actual data, but we count a column in your data table. This means that zero would be reported for any day not having matching data.
If you are using postgreSQL, you could generate series with necessary dates period.
SELECT
t1.date,
COUNT(DISTINCT t2.file_col) AS d_cnt,
COUNT(t2.file_col) AS cnt
FROM
(
select to_char( '?'::DATE + (interval '1' month * generate_series(0,11)),'yyyy-mm-dd')as month) x
...
) t1
LEFT JOIN tab1 t2
ON t1.date = to_char(t2.date_col,'yyyy-mm')
WHERE
t1.date BETWEEN 'date1' and 'date2'
GROUP BY
t1.date;
In this example show how to generate sequence for month period.