Lag function for dates in SQL - sql

I am using LAG SQL function to get the difference of 2 consecutive dates in the records. THe issue is, the result it is returning is in DATE -TIME format whereas I want it either to be in Days, or hours. Attached is Output it outcome and the expected result.
Code:
select
*,
(action_date - lag(action_date) over (partition by voucher_no order by action_date)) as diff
from cte3

I would recommend using time for the last column -- although it does give you seconds as well:
SELECT DATEDIFF(day, LAG(Date) OVER (ORDER BY Date), Date ) AS diff_day,
CONVERT(TIME, Date - LAG(Date) OVER (ORDER BY Date)) as time
FROM t;
It is simple enough to convert this to just HH:MM format if you prefer:
SELECT DATEDIFF(day, LAG(Date) OVER (ORDER BY Date), Date ) AS diff_day,
CONVERT(VARCHAR(5), CONVERT(TIME, Date - LAG(Date) OVER (ORDER BY Date))) as time_hhmm
FROM t;
Here is a db<>fiddle.
I prefer this method because it is easier to format the time. In particular, the fiddle includes an example where the time is 00:01 and it is formatted as 00:01 rather than 0:1.

You can use DATEDIFF() function such as
SELECT
DATEDIFF(day, LAG(Date) OVER (ORDER BY Date), Date ) AS diff_day,
CONCAT(
DATEDIFF(minute, LAG(Date) OVER (ORDER BY Date), Date )/60,
':',
DATEDIFF(minute, LAG(Date) OVER (ORDER BY Date), Date )%60
) AS diff_hour_minute, *
FROM t
in order to get the desired difference values.
Demo

Related

how to filter database data in sql server by per hour

if i have the data like the picture above, let's say 1 day data per minute, and i want to filter it to be per hour, so i will have 24 data, because i take the data per hour. how to do that
i have tried some queries, like this one using group by, but the result is not like i want. didn't work for grouping the datas.
SELECT myDatetime FROM datates
WHERE myDatetime >= '2020-03-01 05:30:00'
AND myDatetime < DATEADD(DAY,1,'2020-03-01 07:30:00')
group by myDatetime ,DATEPART(hour,myDatetime )
You can use row_number(). For instance, if you want the first value per hour:
select d.*
from (select d.*,
row_number() over (partition by convert(date, myDatetime), datepart(hour, myDatetime) order by mydatetime) as seqnum
from datates d
) d
where seqnum = 1;
If you want to sum the values, use aggregation:
select dateadd(hour, datepart(hour, myDatetime), convert(datetime, convert(date, myDatetime))),
sum(nilai)
from datates d
group by dateadd(hour, datepart(hour, myDatetime), convert(datetime, convert(date, myDatetime)));

How do I make that difference from months using standardSQL (BigQuery)

I have the following query:
#standardSQL
SELECT distinct (grand_total/months) AS avg, ((grand_total/days)) AS
avg_day
FROM
(select count(searchint.id) as Total, (DATE_DIFF(DATE ({{DATE_END}}),
DATE ({{DATE_START}}), DAY)+1) AS days, ((12 * YEAR(TIMESTAMP({{DATE_END}})) +
MONTH(TIMESTAMP({{DATE_END}}))) - (12 * YEAR(TIMESTAMP({{DATE_START}}))
+ MONTH(TIMESTAMP({{DATE_START}}))) +1) AS months,
(select count(searchint.id) as Total
from `dbsearch`
where cast(replace(searchint.createdDate,'Z','')as DateTime) >=
cast({{DATE_START}} as DateTime)
and cast(replace(searchint.createdDate,'Z','')as DateTime) <=
cast(DATE_ADD(cast({{DATE_END}} as date), Interval 1 day ) as DateTime)) AS grand_total
from `dbsearch`
where cast(replace(searchint.createdDate,'Z','')as DateTime) >=
cast({{DATE_START}} as DateTime)
and cast(replace(searchint.createdDate,'Z','')as DateTime) <=
cast(DATE_ADD(cast({{DATE_END}} as date), Interval 1 day ) as DateTime)
group by date(cast(replace(searchint.createdDate,'Z','')as DateTime))
ORDER BY 2 DESC) AS groupby
However, when I try to run BigQuery it gives the following error:
Function not found: YEAR at [5:180]
I understand it's because I'm using standardSQL, but how do I make that difference from months using standardSQL?
To find difference in months between two dates you better to use DATE_DIFF()
DATE_DIFF(DATE_END, DATE_START, MONTH)
StandardSQL in BigQuery supports the ISO/ANSI-standard function for extracting date parts. This is extract():
You want:
extract(year from <datecol>)
extract(month from <datecol>)
This is explained in the documentation.

How can I select one row of data per hour?

I'm new at sql.
There is something that makes me confused, i got data per minute, but i only need a row of it per hour or per 2 hours. For example when i select data from the previous day, it shows me 1440 rows and i need to reduce them to less rows to make some charts.
Thanks in advance.
when i use this query:
select [Value],[Time] from [AbsoluteData] where [Sensor] = '5100' and [Time] >= dateadd(day,datediff(day,1,GETDATE()),0) AND[Time] < dateadd(day, datediff(day, 0, GETDATE()), 0)
i got:
You can select on row per hour by using row_number() like this:
select t.*
from (select t.*,
row_number() over (partition by cast(datetimecol as date), datepart(hour, datetimecol)
order by datetimecol
) as seqnum
from t
) t
where seqnum = 1;
I cannot read your image and you don't have a sample query or sample data, so this uses generic names.
If the data drops in every minute and you want just one within a given range (last hour or last day), just restrict the rows to the range and pick 1:
select top 1
[Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
(last one yesterday)
or:
set rowcount 1;
select [Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
set rowcount 0;

Summing a column by all transactions in a day

I'm trying to sum up all transactions for each day in my database.
SELECT DISTINCT
SUM(Balance) OVER (partition by Date) AS account_total,
Date
FROM tbl_FundData
ORDER BY Date;
The problem with the output is if a transaction is completed at a different time it becomes its own unique sum instead of rolling into the one day. I'm not sure how to modify the query to fix this.
I'm using SQL Server 2008 (I think)
Seems yo use DateTime as column data type so cast it as DATE :
SELECT DISTINCT SUM(Balance) OVER (partition by CAST([Date] AS DATE)) AS account_total, CAST([Date] AS DATE)
FROM tbl_FundData
ORDER BY CAST([Date] AS DATE);
Also you'd better use Group By in this case as :
SELECT SUM(Balance) AS account_total, CAST([Date] AS DATE)
FROM tbl_FundData
GROUP BY CAST([Date] AS DATE);
SELECT DISTINCT
SUM(Balance) OVER (partition by convert(varchar, Date, 103)) AS account_total,
convert(varchar, Date, 103) Date
FROM tbl_FundData
ORDER BY convert(varchar,Date,103)
SELECT SUM(Balance) account_total
,CAST(FLOOR(CAST(IssueDate AS FLOAT)) AS DATETIME) IssueDate
FROM tbl_FundData
GROUP BY
CAST(FLOOR(CAST(IssueDate AS FLOAT)) AS DATETIME)
ORDER BY
CAST(FLOOR(CAST(IssueDate AS FLOAT)) AS DATETIME)
I guess you have a timestamp as well in your date that's why you get unique values when you sum. Use this:
SELECT sum(balance)
FROM tbl_FundData
GROUP BY convert(date ,date, 106)
106 is a format for date. But you could use whatever.

Using DATEDIFF within a SELECT

SELECT DISTINCT
Test,
FIRST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) StartDate,
LAST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) EndDate,
DATEDIFF(MONTH, StartDate, EndDate)
FROM
Tests
Any ideas on how I can include the difference between the 2 dates within the SELECT?
I want to be able to use the values StartDate and EndDate however I'm getting an error saying StartDate and EndDate are invalid columns.
You can't use aliases you created in the SELECT clause elsewhere in the same SELECT clause, so you need to place your FIRST_VALUE() and LAST_VALUE() functions within the DATEDIFF() function:
SELECT DISTINCT
Test,
FIRST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) StartDate,
LAST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) EndDate,
DATEDIFF(MONTH, FIRST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC)
, LAST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) )
FROM
Tests
Or you could run everything but the DATEDIFF() in a subquery/cte:
SELECT *,DATEDIFF(MONTH, StartDate, EndDate)
FROM (SELECT DISTINCT
Test,
FIRST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) StartDate,
LAST_VALUE (CONVERT(DATE, datetime)) OVER (ORDER BY datetime DESC) EndDate
FROM
Tests
) AS sub
You also can't use aliases created in the SELECT clause in the WHERE clause, but you can use them in ORDER BY and of course in any outer queries.
As a note, I think your query is equivalent to:
SELECT Test,
CONVERT(DATE, MIN(datetime)) as StartDate,
CONVERT(DATE, MAX(datetime) as EndDate,
DATEDIFF(MONTH, CONVERT(DATE, MIN(datetime)), CONVERT(DATE, MAX(datetime)))
FROM Tests
GROUP BY Test;
The functions MIN() and MAX() are more succinct. In addition, the query is easier to read as a group by rather than as a select distinct.