SQL - Lead function to get dates from next row [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
I have a table with a date and value for example:
AccID Date Value
1 01/01/2007 10
1 01/02/2008 20
1 01/03/2009 40
I want to create a new table that starts from the date in row 1 and ends with the date in row 2 and so on.....for example
AccID Date DateEnd Value
1 01/01/2007 01/02/2008 10
1 01/02/2008 01/03/2009 20
1 01/03/2009 01/04/2050 40
Select
date,
isnull(lead(date) over (partition by accID order by date), '01/04/2050') as DateEnd,
value
from column A
I have tried this code but I can't seem to get the correct output. This is the output I am currently getting
AccID Date DateEnd Value
1 01/02/2008 01/02/2009 20
1 01/02/2009 01/03/2007 40
1 01/01/2007 01/04/2050 10

You are not getting any output, you are getting an error
Incorrect syntax near 'partition'.
You get the correct results when you correct the error
Select
date,
isnull(lead(date) over (partition by accID order by date), '01/04/2050') as DateEnd,
value
from column A
Edit: Do yourself some favours and apply the following:
Avoid the use of reserved words or if you "must" use them, surround the column or table name with [ ] e.g. [date], [value],[column]
Research the function you're going to use to make the most of what it has to offer, to simplify your queries e.g. See the documentaion for Lead
Use date formats that are unambiguous e.g. '2050-04-01' in preference to '01/04/2050'. The latter could be either 1st April or 4th January depending on where in the world you happen to be

Related

SQL - How to order by two columns [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
Imagine we have a table 'user' with several different column. Two of them are date (date) and isValid (boolean). I would like to write sql what sort this by two columns (date and isValid). First of all i would like to sort by date ASC, then every row what has isValid = 1 should be after all row with isValid = 0. So even if have a row with date = 2022.01.01 with isValid = 0 should be before row with date 2021.01.01
Initial Data:
Date IsValid
2023 0
2022 1
2025 0
2024 1
2026 0
Expected Data:
Date IsValid
2023 0
2025 0
2026 0
2022 1
2024 1
With a comma between the columns...
SELECT
date,
isValid
FROM
yourTable
ORDER BY
isValid,
date
based on your edit your ordering of column will be changed isvalid will come first then date so I changed my answer like below
order by isValid, date
You will need to specify desc for isValid column as it seems that you want true value records first, so your query would be like below:
SELECT * FROM `USER` ORDER BY `DATE`, ISVALID DESC;

SQL query to get time spent on specific statuses based on single datetime column [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I need to build a SQL query in which I can get time spent on multiple statuses (onHold,Waiting for customer,Resolved,Closed), so basically I do not want to include time spent on this statues and table looks like as below
So I need a query in which I can get actual time spent on ticket or time spent on status which I have mentioned so far I have tried below solutions and tried Cross APPLY but seems all did not help me as expected.
Tried below query so far and that gives me correct time spent on first status on-hold not after that:
SELECT t1.TICKETNUMBER,SUM(DATEDIFF(MINUTE,TICKETTIME,CloseTime)) as TotalMinutes
FROM [Admin].[TbtrnTicketHistory] t1
CROSS APPLY(SELECT TOP 1 TICKETTIME as CloseTime FROM [Admin].[TbtrnTicketHistory] t2 WHERE t1.TICKETNUMBER = t2.TICKETNUMBER and t2.TICKETHISTORYID > t1.TICKETHISTORYID ORDER BY t2.TICKETTIME) as t2
WHERE t1.CURRENTSTATUS_ANALYST not in('On-Hold','Waiting For Customer','Resolved','Closed') and t1.ticketnumber = '211135'
GROUP BY t1.TICKETNUMBER;
calculate difference between two times in two rows in sql
Calculate Time Difference Between Two Consecutive Rows
with SQL Server you can use those very usefull windowed functions LEAD and FIRST_VALUE :
select *
,[duration(sec)] = DATEDIFF(SECOND
,ticketTime
,LEAD(ticketTime,1,ticketTime)over(partition by ticketNumber order by ticketTime)
)
,[cumulative duration(sec)] = DATEDIFF( SECOND
, FIRST_VALUE(ticketTime)over(partition by ticketNumber order by ticketTime)
, ticketTime)
from (values
(1,cast('20211101 10:00:01' as datetime))
,(1,'20211101 10:00:33')
,(1,'20211101 10:01:59')
)T(ticketNumber,ticketTime)
ticketNumber
ticketTime
duration(sec)
cumulative duration(sec)
1
2021-11-01 10:00:01.000
32
0
1
2021-11-01 10:00:33.000
86
32
1
2021-11-01 10:01:59.000
0
118

Get the rows with the latest date for an ID [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
My table has multiple rows for each id, with a calculated score and the date the calculation was done. Simplifying, it looks like this:
id
calc_score
date
1
82
today
1
53
yesterday
1
92
last week
2
23
today
2
60
yesterday
2
73
last week
I need a query that returns only today's scores for each ID. I tried various combinations of group by and distinct on but didn't get very far.
What's the best way for doing this?
PG has several ways. A simple approach is window functions, row_number, rank, etc.
The following will answer the question in your title, to return the latest (last) row per id (by date), which is different than the body of your question.
WITH cte AS (
SELECT t.*
, row_number() OVER (PARTITION BY id ORDER BY date DESC) AS rn
FROM scores
)
SELECT * FROM cte
WHERE rn = 1
;
This just picks the (latest dated) first row for each id based on the date column descending. This also assumes the date column really contains date values or something orderable like a date.
To answer your question in the question body:
I need a query that returns only today's scores for each ID
more strictly, we could also do this:
SELECT *
FROM scores
WHERE date = current_date
;
If you want only today's scores, then you could use a direct comparison if the date has no time component:
where date = current_date
Or for either dates or timestamps:
where date >= current_date and date < current_date + interval '1 day'
If you want the most recent row per id, you would use distinct on:
select distinct on (id) t.*
from t
order by id, date desc;

SQL advanced sorting [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm facing a problem with sorting groups of data in a very old (13 years or so) SQL database program. The data looks like this:
Entry Batch Time
1 1 7-1-2013 13:35
2 1 3-3-2014 7:48
3 1 1-2-2014 18:49
4 2 3-1-2011 13:23
5 2 5-3-2014 20:48
6 2 7-2-2014 3:11
7 3 2-3-2012 15:09
8 3 5-3-2014 10:37
9 3 6-2-2014 7:16
I want to sort the entries by grouping those from the same batches together, and then sort them based on the lowest time entry in those groups. In this example, the group order would be 2-3-1 and the entry order would be 4-6-5-9-7-8-1-3-2.
Is there any easy way to do this? I tried working with order by (select blah), but no success so far. Any help would be much appreciated :)
If I am reading correctly, you want to sort on groups by the oldest date in the group first and then by time.
If this were oracle or sql server, you could use analytics for this:
select Entry,
Batch,
Time
from ( select Entry,
Batch,
Time,
MIN(Time) OVER (PARTITION BY Batch) AS MinTime
from MyTable ) MyTable2
order by MinTime, Time
If you do not have a database that supports this, you could try the following:
select MyTable.Entry,
MyTable.Batch,
MyTable.Time
from MyTable
join ( select Batch, MIN(Time) AS MinTime
from MyTable ) MyTable2 on MyTable.Batch = MyTable2.Batch
order by MyTable2.MinTime, MyTable.Time

DIFFICULT SQL issue [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Bear in mind this needs to be done in SQL - not PL/SQL, no while loops in play here.
I need to go from a single row with an amount, to multiple rows with the amount spread out. Here's the details;
I have a rule that awards in-lieu hours when an employee is short for a period. However, this rule awards ALL the hours on the last day of the period, and the client wants it spread out 8 hrs/day.
For example, if an EE is short 25 hours - the existing rule will award that 25 hours on the last day of the period. Client wants 8 hours on last day, 8 hours on 2nd last day, 8 hrs on 3rd last day, 1 hr on 4th last day.
My SQL is great, but I'm drawing a blank on this one. Any suggestions? Again, no PL/SQL or while loops allowed, has to be done in SQL (Oracle).
Sample data
Start with this;
**ID Date Amount**
1 09/30/2013 25
Need to end up with this;
**ID Date Amount**
1 09/30/2013 8
1 09/29/2013 8
1 09/28/2013 8
1 09/27/2013 1
Provided that those periods do not overlap for a single employee, you may also try something like this:
select distinct id, "date"-(level-1) "date", least(amount-(level-1)*8, 8) amount
from sample_data
connect by amount > (level-1)*8
order by id, "date" desc
If you create a table with all the possible days, you could then cross-join to that. Maybe that table has an actual date, but it also has a day number on each row: 1, 2, 3, 4... where that is the order in which you want to allocate the hours: i.e. 8 hours to day #1, any remaining (but max 8) to day # 2, and so on.
For any particular day_num, the expression ( (day_num - 1) * 8 ) will give you the max. hours that could be allocated already. Only if the employee has hours over this, does this particular day get an allocation. Also, the allocation has to be limited to 8.
The SQL would look something like below. (See this SQL fiddle for schema)
select emp_id, total_hours, day_num,
case
when total_hours - ((day_num-1) * 8) > 8 then 8
when total_hours - ((day_num-1) * 8) < 0 then 0
else total_hours - ((day_num-1) * 8)
end hours_for_day
from emp_short
cross join all_days
where total_hours - ((day_num-1) * 8) > 0