This question already has answers here:
Is there a way to access the "previous row" value in a SELECT statement?
(9 answers)
Closed 8 months ago.
How can I get the result in the PreviousDay column that the day should be -1 from the day in efdt column for all rows?
If the efdt date is 2001-04-02 the result in PreviousDay should be 2001-04-01 and DATEDIFF is 334
Image attached with it please refer it.
You can use the SQL Server LEAD window function over the "efdt" field, which will take the following value given two clauses:
PARTITION BY, which indicates the groups to work on
ORDER BY, which decided which value to take according to an order imposed by one (or more) of your fields.
SELECT T.*,
DATEDIFF(DAY, efdt, PreviousDay)
FROM (SELECT T1.*,
LEAD(efdt) OVER(PARTITION BY emcd ORDER BY efdt) AS PreviousDay
FROM psf206 T1) AS T
ORDER BY emcd, efdt
Check the demo here.
Note: if you want one day less for each row, just add -1 after the DATEDIFF operation (demo).
Related
I'm not sure if I'm asking this question right, but hopefully I can explain it well enough. I have a table that has a Date, Value, and WeekEndDate column. I want to create a sequence column that counts the distinct weeks from 1-13 and cycles every 13 weeks.
I attached a small sample of the output I'm trying to create. Is this even possible?
Use dense_rank() and some arithmetic:
select t.*,
((dense_rank() over (order by weekEnd) - 1) % 13) + 1
from t;
I have 4 columns (two columns filter) and one column date and one column flag.
For a combination of column 1 and column 2, and the open flag, I want to find the open date, the close date and number of days where it was open.
Here is my example and what I want to find with SQL is with the blue/grey color
You can use DATEDIFF() function as shown below if you have already two dates available as OpenDate and CloseDate in your case.
Select DATEDIFF(DAY, OpenDate, CloseDate) as NumberOfOpenDays from YourTable
This looks a gaps-and-islands problem -- but the islands are already defined by opendt (and perhaps col1 and col2).
So, you can just use row_number():
select row_number() over (partition by col1, col2, opendt order by effectivedt)
I am trying to create following logic in Alteryx and data is coming from Exasol database.
Column “Sum_Qty_28_days“ should sum up the values of “Qty ” column for same article which falls under last 28 days.
My sample data looks like:
and I want following output:
E.g. “Sum_Qty_28_days” value for “article” = ‘A’ and date = ‘’2019-10-8” is 8 because it is summing up the “Qty” values associated with dates (coming within previous 28 days) Which are:
2019-09-15
2019-10-05
2019-10-08
for “article” = ‘A’.
Is this possible using SQL window function?
I tried myself with following code:
SUM("Qty") OVER (PARTITION BY "article", date_trunc('month',"Date")
ORDER BY "Date")
But, it is far from what I need. It is summing up the Qty for dates falling in same month. However, I need to sum of Qty for last 28 days.
Thanks in advance.
Yes, this is possible using standard SQL and in many databases. However, this will not work in all databases:
select t.*,
sum(qty) over (partition by article
order by date
range between interval '27 day' preceding and current row
) as sum_qty_28_days
from t;
If your RDBMS does not support the range frame, an alternative solution is to use an inline subquery:
select
t.*,
(
select sum(t1.qty)
from mytable t1
where
t1.article = t.article
and t1.date between t.date - interval 28 days and t.date
) sum_qty_28_days
from mytable t
This question already has answers here:
How can I include null values in a MIN or MAX?
(7 answers)
Closed 4 years ago.
I am working on a SQL query to pull the minimum begin and maximum end date for recurring classes. The way the database is set up, If the classes are not continuing they have an end date, if the classes are continuing then the end date is null. The field is Data Type datetime.
If the end date is null that is essentially the date I want because it is the maximum end date but I cannot seem to work out how to get that to work? I get whatever the last actual date in that field is and cannot get the query to return either null or better yet a default date that I set.
Thanks in advance
If you want the null date as the max, you can do so with a case expression:
select (case when count(*) = count(enddate) then max(enddate) end)
The count(*) = count(enddate) basically says that none of the enddate values are NULL.
If you like playing around with functions, you can also use:
select nullif(max(coalesce(enddate, '9999-01-01')), '9999-01-01')
But I prefer the first method.
I work for a sports film analysis company. We have teams with unique team IDs and I would like to find the number of consecutive weeks they have uploaded film to our site moving backwards from today. Each upload also has its own row in a separate table that I can join on teamid and has a unique date of when it was uploaded. So far I put together a simple query that pulls each unique DATEDIFF(week) value and groups on teamid.
Select teamid, MAX(weekdiff)
(Select teamid, DATEDIFF(week, dateuploaded, GETDATE()) as weekdiff
from leroy_events
group by teamid, weekdiff)
What I am given is a list of teamIDs and unique weekly date differences. I would like to then find the max for each teamID without breaking an increment of 1. For example, if my data set is:
Team datediff
11453 0
11453 1
11453 2
11453 5
11453 7
11453 13
I would like the max value for team: 11453 to be 2.
Any ideas would be awesome.
I have simplified your example assuming that I already have a table with weekdiff column. That would be what you're doing with DATEDIFF to calculate it.
First, I'm using LAG() window function to assign previous value (in ordered set) of a weekdiff to the current row.
Then, using a WHERE condition I'm retrieving max(weekdiff) value that has a previous value which is current_value - 1 for consecutive weekdiffs.
Data:
create table leroy_events ( teamid int, weekdiff int);
insert into leroy_events values (11453,0),(11453,1),(11453,2),(11453,5),(11453,7),(11453,13);
Code:
WITH initial_data AS (
Select
teamid,
weekdiff,
lag(weekdiff,1) over (partition by teamid order by weekdiff) as lag_weekdiff
from
leroy_events
)
SELECT
teamid,
max(weekdiff) AS max_weekdiff_consecutive
FROM
initial_data
WHERE weekdiff = lag_weekdiff + 1 -- this insures retrieving max() without breaking your consecutive increment
GROUP BY 1
SQLFiddle with your sample data to see how this code works.
Result:
teamid max_weekdiff_consecutive
11453 2
You can use SQL window functions to probe relationships between rows of the table. In this case the lag() function can be used to look at the previous row relative to a given order and grouping. That way you can determine whether a given row is part of a group of consecutive rows.
You still need overall to aggregate or filter to reduce the number of rows for each group of interest (i.e. each team) to 1. It's convenient in this case to aggregate. Overall, it might look like this:
select
team,
case min(datediff)
when 0 then max(datediff)
else -1
end as max_weeks
from (
select
team,
datediff,
case
when (lag(datediff) over (partition by team order by datediff) != datediff - 1)
then 0
else 1
end as is_consec
from diffs
) cd
where is_consec = 1
group by team
The inline view just adds an is_consec column to the data, marking whether each row is part of a group of consecutive rows. The outer query filters on that column (you cannot filter directly on a window function), and chooses the maximum datediff from the remaining rows for each team.
There are a few subtleties there:
The case expression in the inline view is written as it is to exploit the fact that the lag() computed for the first row of each partition will be NULL, which does not evaluate unequal (nor equal) to any value. Thus the first row in each partition is always marked consecutive.
The case testing min(datediff) in the outer select clause picks up teams that have no record with datediff = 0, and assigns -1 to column max_weeks for them.
It would also have been possible to mark rows non-consecutive if the first in their group did not have datediff = 0, but then you would lose such teams from the results altogether.