datediff between 2 asymmetric column from same table - sql

how can i use date difference between two asymmetric row from same table?
select
[endtime]
,[realtime]
from [prin]
where ([realtime] is not null) and ([endtime] is not null and)
order by [realtime]
between end date time and next start date time

Use the DateDiff function to get the difference between two dates.
Add the day parameter to get the difference in days.
SELECT
[endtime]
,[realtime]
,datediff (day,[endtime],lead ([realtime]) over (order by [realtime])) as days_endtime_2_next_realtime
FROM [prin]
WHERE ([realtime] is not null)
AND ([endtime] is not null)
ORDER BY [realtime]

create table #a
(
date_1 date,
date_2 date
)
insert into #a values
('1-10-16','2-10-16'),
('2-10-16','3-10-16'),
('3-10-16','4-10-16')
;with cte as
(
select
date_1,date_2
,lead(date_2,1) over (order by date_2 ) as lead_value
from #a
where (date_1 is not null) and (date_2 is not null )
)
select date_1,date_2,
datediff(Day,date_1,lead_value) as diffrence from cte

Related

How can I print the second row value in the first row column?

I have fetching data as follows:
start_date end_date amount
12/10/2020 - 1800000
12/18/2020 - 1200000
01/18/2021 - 1000000
I would like to print the start date of the second row to the end date of the first row for X rows I am fetching so that the table becomes as follows:
start_date end_date amount
12/10/2020 12/18/2020 1800000
12/18/2020 01/18/2021 1200000
01/18/2021 - 1000000
Thanks everyone!
Use LEAD as follows:
select start_Date,
lead(start_date) over (order by start_Date) as end_Date
amount
from your_Table t
Use lead, if you have no column for partition by, use only order by in the over()
select start_date,
lead(start_date) over (partition by ... order by start_date) as end_date,
amount
...
Used the sample table and selected the data. Please change the SQL query as per your need.
DECLARE #Range TABLE (
start_date DATETIME
,end_date DATETIME
,amount INT
)
INSERT #Range
SELECT '12/10/2020'
,NULL
,1800000
UNION ALL
SELECT '12/18/2020'
,NULL
,1200000
UNION ALL
SELECT '01/18/2021'
,NULL
,1000000
SELECT start_date
,LEAD(start_date, 1) OVER (
ORDER BY start_date
) AS end_date
,amount
FROM #Range;
Another option for LEAD by using Recursive CTE
DECLARE #T TABLE(start_date DATE, end_date DATE, amount INT)
Insert into #T VALUES
('12/10/2020',NULL,1800000),
('12/18/2020',NULL,1200000),
('01/18/2021',NULL,1000000)
;WITH CTE AS(
SELECT rownum = ROW_NUMBER() OVER(ORDER BY End_Date),amount,Start_Date,End_Date
FROM #T
)
SELECT
CTE.start_date,CTE.amount,Nex.start_date AS[End Date]
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1

SQL Selecting the earliest date from many within a row

I am working in MS SQL Server Management Studio. I have created a view keyed on patientId, each patient/row has 12 associated dates. Is there a way in SQL that I can find the min and max dates for each row?
Any help would be much appreciated.
You can use "unpivot". Check the example below:
CREATE TABLE dates
(
number INT PRIMARY KEY ,
date1 DATETIME ,
date2 DATETIME ,
date3 DATETIME
)
INSERT INTO dates
VALUES ( 1, '1/1/2018', '2/4/2018', '3/1/2018')
INSERT INTO dates
VALUES ( 2, '1/2/2018', '2/3/2018', '3/3/2018')
INSERT INTO dates
VALUES ( 3, '1/3/2018', '2/2/2018', '3/2/2018')
INSERT INTO dates
VALUES ( 4, '1/4/2018', '2/1/2018', '3/4/2018')
GO
SELECT number ,
MIN(dDate) mindate,
MAX(dDate) maxDate
FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,Date3 ) ) as u
GROUP BY number
GO
I would do this using cross apply:
select t.*, v.mind, v.maxd
from t cross apply
(select min(v.d) as mind, max(v.d) as maxd
from (values (d1), (d2), (d3), (d4), (d5), (d6), (d7), (d8), (d9), (d10), (d11), (d12)
) v(d)
) v;
Note that min() and max() ignore NULL values.
Another way:
create table MyDates
(
ID int,
D1 datetime,
D2 datetime,
D3 datetime
)
insert MyDates(ID, D1, D2, D3)
values (1, '19000101', '19720506', '20060204'),
(2, '20170624', '20180821', '20180901'),
(3, '19820202', '19840721', '19851231')
select *,
(select min(v) from (values(D1), (D2), (D3)) t(v)) [Min],
(select max(v) from (values(D1), (D2), (D3)) t(v)) [Max]
from MyDates

How to add an extra temp date column using the select query in SQL Server

I am trying to add an extra date column in the select statement using a certain where condition.
Below is my current table:
table
I want to add an extra Date column which is add all date between >=Start and <= End-2.
output
Getting error with this query:
SELECT
*, temp_Date AS Date
FROM
Mytable
WHERE
Date >= Start AND Date <= End - 2
Thanks in advance.
Consider this statement as dummy data:
CREATE TABLE MyTable
(
id int not null,
startDate date not null,
endDate date not null,
val int not null
)
insert into MyTable
values
(10,'20171106','20171112',7),
(10,'20171106','20171112',6),
(10,'20171106','20171112',5),
(10,'20171106','20171112',0),
(10,'20171106','20171112',2)
Using recursive CTE you select each tuple as your starting date and increment that date until it reaches the enddate like this:
;WITH rc AS (
SELECT id, startDate, endDate, val
, startDate AS temp_date
FROM MyTable
UNION ALL
SELECT id, startDate, endDate, val
, DATEADD(DAY,1,temp_date)
FROM rc
WHERE DATEADD(DAY,1,temp_date) <= enddate
)
SELECT *
FROM rc
You should be aware the recursion in SQL-Server is expensive and slow on larger data. Also remember to hint the maximum recursive loop amounts as the default is 100. Example:
OPTION (MAXRECURSION 0)
The 0 would be unlimited recursions, with the risk of running infinitely.
As I read you are using a data warehouse and as such it should have a time or date dimension. In such case a simple join would do the work:
SELECT id, startDate, endDate, val
, date_sid AS temp_date
FROM MyTable AS m
INNER JOIN DimDate AS dd
ON dd.date_sid >= startDate
AND dd.date_sid <= endDate
Please consider not using reserved keys for column names (like start, end or value)
Try this:
Select M.*
, Temp_date = Datediff(day, M.start, dateadd(day,-2,M.end))
from MyTable M

Finding the maximum value in a 24h period SQL

In need of some help :)
So I have a table of records with the following columns:
Key (PK, FK, int)
DT (smalldatetime)
Value (real)
The DT is a datetime for every half hour of the day with an associated value
E.g.
Key DT VALUE
1000 2010-01-01 08:00:00 80
1000 2010-01-01 08:30:00 75
1000 2010-01-01 09:00:00 100
I need to find the max value and associated DT for every 24 hour period. for a particular key and date range
Currently I have:
SELECT CAST(LEFT([DT],11) as smalldatetime) as 'DATE'
,max([VALUE]) as 'MAX_HH'
FROM TABLE 1
WHERE DT > '6-nov-2016' and [KEY] = '1000'
GROUP BY CAST(LEFT([DT],11) as smalldatetime)
ORDER BY 'DATE'
But this returns the max values for the date e.g.
Key DT VALUE
1000 2010-01-01 00:00:00 100
Any ideas on how to pull the full DT ?
Thanks guys!
Assuming you're using a database with support for windowed functions, we can use ROW_NUMBER() (or RANK if you want to support/pull in values that are tied for first place):
declare #t table ([Key] int not null , DT smalldatetime not null, Value int not null)
insert into #t([Key],DT,VALUE) values
(1000,'2010-01-01T08:00:00',80 ),
(1000,'2010-01-01T08:30:00',75 ),
(1000,'2010-01-01T09:00:00',100)
;With Numbered as (
select *,
ROW_NUMBER() OVER (PARTITION BY [Key],CAST(DT as date) ORDER BY Value desc) as rn
from #t
)
select * from Numbered
where rn=1
Damien's answer is very good, if you can't (or want) to use windowed function, try this:
SELECT T1.*
FROM TABLE_1 AS T1
INNER JOIN (
SELECT CAST([DT] as date) as 'DATE'
, MAX([VALUE]) as 'MAX_HH'
FROM TABLE_1
WHERE DT > '6-nov-2016' and [KEY] = '1000'
GROUP BY CAST([DT] as date)
) AS MAX_DT
ON MAX_DT.[DATE] = CAST(T1.[DT] as date)
AND T1.VALUE = MAX_DT.MAX_HH
WHERE DT > '6-nov-2016' and [KEY] = '1000'
ORDER BY DT
By the way, it's best not to use reserved keywords as object names (i.e. date)

SQL query to get number of days between dates

I have a table in SQL where one column contains lots of IDS some of which are duplicate, a second column with lots of dates all different
I want to create a table where i have unique list of IDS down the left hand side of the table, a column called number of days and then in the table the number of days between the last date and the second to last date that are in the table.
Using Row_Number() in concert with a conditional aggregation.
Example
Declare #YourTable Table ([ID] varchar(50),[DateCol] date)
Insert Into #YourTable Values
(1,'2017-05-01')
,(1,'2017-05-05')
,(1,'2017-05-10') -- 2nd
,(1,'2017-05-31') -- Lst 21 days
,(2,'2017-05-01')
,(2,'2017-06-05')
,(2,'2017-06-10') -- 2nd
,(2,'2017-07-31') -- Lst 51 days
Select ID
,Days = DateDiff(DAY,max(case when RN=2 then DateCol end),max(case when RN=1 then DateCol end))
From (
Select *
,RN = Row_Number() over (Partition By ID Order by DateCol Desc)
from #YourTable
) A
Group By ID
Returns
ID Days
1 21
2 51
Here I take the MAX(DateCol) that is less than the subqueried MAX(DateCol) with the same ID- this is used in the DateDiff.
SELECT dT.ID
,(SELECT MAX(DateCol)
FROM #YourTable Y
WHERE Y.DateCol < dT.MaxDateCol --Date less than MAX
AND Y.ID = dT.ID
) AS [Date less than MAX] --added by request
,dT.MaxDateCol AS [Max Date] --added by request
,DATEDIFF(DAY, (SELECT MAX(DateCol)
FROM #YourTable Y
WHERE Y.DateCol < dT.MaxDateCol --Date less than MAX
AND Y.ID = dT.ID
)
, dT.MaxDateCol
) AS [Days Difference] --datediff between max and date less than MAX
FROM (
SELECT ID
,MAX([DateCol]) [MaxDateCol] --MAX, removes duplicate ID's.
FROM #YourTable
GROUP BY ID
) AS dT