My question is similar to how to generate Serial numbers +Add 1 in select statement
But I need the seq as below in Oracle sql
table 1 data:
facility store stop_seq
32 729 1
32 380 2
32 603 3
12 722 4
12 671 5
48 423 6
I need result as below:
facility res_seq
32 1
12 2
48 3
Here res_seq should be order by based on stop_seq in tabel 1
Please help
select facility, row_number() over(order by max(stop_seq)) res_seq
from your_tab group by facility;
ROW_NUMBER is explained in the link posted in the question
Analytic functions are performed after GROUP BY, so in this query the data is aggregated by facility and then row numbers are assigned
Related
I have a user request for a report and I’m too new to SQL programming to know how to approach it.
My user wants to know for each Staff ID what is the min, avg and max number of days between visits. What I don’t know how to figure out is the number of days between Visit 1 and Visit 2; Visit 2 and Visit 3, etc., for each Person ID. Some Person ID’s only have one visit, others (most) have multiple visits (up to 26). Here is a snapshot of some data (the full dataset is over 14k records):
PersonID VisitNo StaffID VisitDate
161 1 42344 06/19/2018
163 1 32987 05/14/2018
163 2 32987 09/17/2018
193 1 42344 04/09/2018
193 2 42344 07/18/2018
193 1 33865 07/18/2018
207 1 32987 10/10/2018
207 2 32987 11/05/2018
329 1 42344 04/15/2018
329 2 42344 05/23/2018
329 3 42344 06/10/2018
329 4 42344 07/18/2018
329 1 33865 06/30/2018
329 2 33865 09/14/2018
My research found a lot of references to comparing rows in the same table and I figured out how to compare one visit to the next for a single PersonID using a self join and datadiff, but how do I get from one PersonID to the next, or skip those PersonID’s with only 1 visit? Or a PersonID who has visits with multiple StaffId's?
Any ideas/suggestions are greatly appreciated as I have two requests that will benefit.
You can use analytic function LEAD (myvar,1) OVER ()
example from https://www.techonthenet.com/sql_server/functions/lead.php
SELECT dept_id, last_name, salary,
LEAD (salary,1) OVER (ORDER BY salary) AS next_highest_salary
FROM employees;
For the average number of days, you can just use aggregation:
select personid,
(datediff(day, min(visitdate), max(visitdate)) * 1.0 / nullif(count(*) - 1, 0)
from t
group by personid;
I used SQL Server syntax, but the same idea holds in any database. The average is the maximum minus the minimum divided by one less than the number of visits.
I have a TSQL query which gives a max value of the trend data for the given result set. I would like to get this data based on each month's result. (I have a datetime column in the result set ). If I select data for three months it has to give this vaules for each month. Right now it looks for the max values and give the same result for all the months.
Below is the expression i use to get the trend result. It's part of select statement with number of other columns.
select col1, col2, sampledatecollected, (Select MAX(AvailMemSlope) FROM SlopeCTE) * MetricID + (Select MAX (AvailMemIntercept) FROM InterceptCTE) AS AvailMemTrend
I think i might need to do something like this but given the expression i'm little confused as to how to get the desired results
select name, max(value)
from tbl1
group by name
CPUTrend id the data i get from the expression i specified in the first query.
sample data:
Date AVGCPU MAXCPU CPUTrend
8/22/2016 20 40 44
8/23/2016 20 40 44
8/24/2016 20 40 44
8/25/2016 20 40 44
9/22/2016 20 50 44
9/23/2016 20 50 44
9/24/2016 20 50 44
Expected result:
Date AVGCPU MAXCPU CPUTrend
8/22/2016 20 40 32
8/23/2016 20 40 32
8/24/2016 20 40 32
8/25/2016 20 40 32
9/22/2016 20 50 44
9/23/2016 20 50 44
9/24/2016 20 50 44
Right now all i get is 44 as it's the maximum value.
I think you just want a subquery:
with t as (
select col1, col2, sampledatecollected,
(Select MAX(AvailMemSlope) FROM SlopeCTE) * MetricID +
(Select MAX (AvailMemIntercept) FROM InterceptCTE) AS AvailMemTrend
from ?? -- the SQL in your question is incomplete
)
select year(sampledatecollected), month(sampledatecollected),
max(AvailMemTrend)
from t
group by year(sampledatecollected), month(sampledatecollected)
order by year(sampledatecollected), month(sampledatecollected);
I have a table ScheduleRotationDetail that contains these as columns:
ScheduleRotationID ScheduleID Ordinal Duration
379 61 1 1
379 379 2 20
379 512 3 1
379 89 4 20
I have a query that goes like this in order to get the day of the year each schedule is supposed to start on:
SELECT ScheduleID, Ordinal, Duration,
,Duration * 7 AS DurationDays
,( SELECT ( ISNULL( SUM(ISNULL( Duration, 0 )), 0 ) - 1 ) * 7
FROM ScheduleRotationDetail WHERE ScheduleRotationID = srd.ScheduleRotationID
AND Ordinal <= srd.Ordinal ) AS StartDay
FROM ScheduleRotationDetail srd
WHERE srd.ScheduleRotationID = 379
That outputs this as the result set:
ScheduleID Ordinal Duration DurationDays StartDay
61 1 1 7 0
379 2 20 140 140
512 3 1 7 147
89 4 20 140 287
Yet what I need the start day column values to be are:
0
7
147
154
I have tried CTEs but can't get it to work so I've come to here for advice.
It looks like you want a cumulative sum. In SQL Server 2012+, you can do:
SELECT ScheduleID, Ordinal, Duration,
SUM(Duration*7) OVER (ORDER BY Ordinal) - Duration*7 as StartDate
FROM ScheduleRotationDetail srd ;
In earlier versions, you can use APPLY for this purpose (or a correlated subquery).
I am using SQL Server 2012,
How can I achieve following(Table 2) output from table 1 with sql script/tsql?
Table 1 :Current scenario
--------------------------------------------------
Year ReferredEachYear ActiveEachYear
--------------------------------------------------
2014 297 179
2013 321 144
2012 354 123
2011 317 90
2010 292 72
--------------------------------------------------
Table 2 : Expected OutPut
-------------------------------------------------------------------------
Year ReferredEachYear ActiveEachYear TotalActiveInSystem
-------------------------------------------------------------------------
2014 297 179 608
2013 321 144 429
2012 354 123 285
2011 317 90 162
2010 292 72 72
--------------------------------------------------------------------------
If you are using SQL Server 2012, then you can use the cumulative sum function:
select cs.*,
sum(cs.ActiveEachYear) over (order by cs.[year]) as TotalActiveInSystem
from CurrentScenario cs
order by cs.[year] desc;
This function is not available in earlier versions of SQL Server. You would have to use some other method in those versions (I would use a correlated subquery).
SELECT T.Year,
T.ReferredEachYear
T.ActiveEachYear
(SELECT SUM(ActiveEachYear) FROM YourTable WHERE YourTable.Year <= t.Year) AS TotalActiveinSystem
FROM yourTable T
Just as Gordon already specified, in SQL Server 2012 you can use cumulative sum function. To make it easier to understand the query can be rewritten as follows.
SELECT cs.*
,SUM(cs.ActiveEachYear) OVER
( ORDER BY cs.[year]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS TotalActiveInSystem
FROM CurrentScenario cs
ORDER BY cs.[year] DESC;
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW this statement is referred to as window framing. This query and one in #Gordon's answer will produce same results. When you only specify ORDER BY you are implicitly defining the window frame for the calculation.
By using framing definition you can limit rows that are affected by operation.
Entire documentation on OVER() clause http://technet.microsoft.com/en-us/library/ms189461.aspx
I have a table with an ID and multiple informative columns. Sometimes however, I can have multiple data for an ID, so I added a column called "Sequence". Here is a shortened example:
ID Sequence Name Tel Date Amount
124 1 Bob 873-4356 2001-02-03 10
124 2 Bob 873-4356 2002-03-12 7
124 3 Bob 873-4351 2006-07-08 24
125 1 John 983-4568 2007-02-01 3
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
So, I would like to obtain only these lines:
124 3 Bob 873-4351 2006-07-08 24
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
Anyone could give me a hand on how I could build a SQL query to do this ?
Thanks !
You can calculate the maximum sequence using group by. Then you can use join to get only the maximum in the original data.
Assuming your table is called t:
select t.*
from t join
(select id, MAX(sequence) as maxs
from t
group by id
) tmax
on t.id = tmax.id and
t.sequence = tmax.maxs