Read next record? - sql-server

We are on MS SQL-Server 2012.Users want to know if the time of the patients next admission date is less than 30 days for any reason. Doesn’t have to be seen by same provider
I am not sure how to read the next record, if the MRN ID is the same, then calculate the difference in days between the record you are on and the next next record.
For example:
Record 1 : MRNID =33 Discharge date = 1/1/2016
Record 2 : MRNID = 33 Admission date = 2/2/2016
MRNIDs are the same, so I calculate. Then I compare record 2 to record 3 and do the same process.

Use Lead() window function
select mrnid,
admission_date,
discharge_date,
lead(admission_date) over (partition by mrnid order by admission_date) next_date
from table;
SAMPLE OUTPUT
mnrid admission_date lead(admission_date)
33 2016-01-01 2016-01-02
33 2016-01-02 2016-01-03
33 2016-01-03 2016-01-04
33 2016-01-04 null
34 2016-01-01 2016-01-02
34 2016-01-02 2016-01-03
34 2016-01-03 2016-01-04
34 2016-01-04 null

Related

SSRS - Using specific Row Number

I have a SQL query where I am getting the row number for a count of employees per division and per month at the beginning of the month and the end of the month. To do that, I use a payroll end date which is a weekly date. So in essence I have 4 dates where employee counts are shown. Some months have 5 dates which makes the row count for that month 5 instead of 4.
I then need to build an SSRS report to show only the first employee count and the last employee count per division, per month. I have the first number since I am using =IIF(Fields!RowNumber.Value = 1, Fields!EMPCOUNT.Value, 0)
The problem I have now is getting the last employee count where I need to conditionally select a count where row number needs to be 5 if exists or 4 if it doesn't exist. I'm not sure how to get the expression to work in SSRS. Sample data is below.
PRCo EMPCOUNT udDivision PREndDate ROWNUM Type
1 89 Civil 2018-01-06 00:00:00 1 1
1 97 Civil 2018-01-13 00:00:00 2 1
1 97 Civil 2018-01-20 00:00:00 3 1
1 97 Civil 2018-01-27 00:00:00 4 1
1 16 Colorado 2018-01-06 00:00:00 1 1
1 18 Colorado 2018-01-13 00:00:00 2 1
1 14 Colorado 2018-01-20 00:00:00 3 1
1 10 Colorado 2018-01-27 00:00:00 4 1
1 94 Civil 2018-02-03 00:00:00 1 2
1 91 Civil 2018-02-10 00:00:00 2 2
1 92 Civil 2018-02-17 00:00:00 3 2
1 91 Civil 2018-02-24 00:00:00 4 2
1 16 Colorado 2018-02-03 00:00:00 1 2
1 16 Colorado 2018-02-10 00:00:00 2 2
1 18 Colorado 2018-02-17 00:00:00 3 2
1 19 Colorado 2018-02-24 00:00:00 4 2
1 92 Civil 2018-03-03 00:00:00 1 3
1 91 Civil 2018-03-10 00:00:00 2 3
1 88 Civil 2018-03-17 00:00:00 3 3
1 92 Civil 2018-03-24 00:00:00 4 3
1 90 Civil 2018-03-31 00:00:00 5 3
1 19 Colorado 2018-03-03 00:00:00 1 3
1 26 Colorado 2018-03-10 00:00:00 2 3
1 25 Colorado 2018-03-17 00:00:00 3 3
1 27 Colorado 2018-03-24 00:00:00 4 3
1 24 Colorado 2018-03-31 00:00:00 5 3
I would do this in your query rather than trying to get it to work directly in SSRS. There might be a simpler way than this but this is just based on your existing query.
Please note this is untested and just off the top of my head so it may need some editing before it will work.
SELECT * INTO #t FROM YOUR_EXISTING_QUERY
SELECT DISTINCT
PRCo
, udDivision
, YEAR(PREndDate) AS Yr
, MONTH(PREndDate) AS Mnth
, FIRST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS OpeningEMPCOUNT
, LAST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS CLosing_EMPCOUNT
FROM #t
Yo might need to include Type not sure what this does but you get the idea hopefully.
The FIRST_VALUE and LAST_VALUE functions simply get the first/last value within the partition defined, in your case PRCo, udDivision and then just the year and month portion of the payroll end date, the first and last positions are determined by the order clause, in this case row number.

SQL Server query for Total of hours across multiple rows

I've tried to resolve this a few ways and wanting some extra help.
I'm wanting to return the same number of rows but trying to calculate the number of total hours delivered by each Employee for each service on each day.
I've added a duplicate flag but that doesn't help me to work out the max hours by the 1 employee in 1 day.
Emp Service Date Start End Hrs Duplicate Flag Flag hrs
Fred xyz 14/09/2017 8:45 15:00 6.25 1 1 6.25
Fred xyz 14/09/2017 9:00 14:15 5.25 1 0 0
Fred xyz 14/09/2017 9:00 14:15 5.25 2 0 0
Fred xyz 14/09/2017 9:00 15:00 6 1 0 0
John xyz 15/09/2017 10:00 12:00 2 1 1 2
John xyz 15/09/2017 10:00 13:00 3 1 0 0
John xyz 15/09/2017 11:00 15:00 4 1 0 0
John xyz 15/09/2017 12:00 16:00 4 1 1 4
the last 2 columns are the ones I can't quite work out how to add. I've tried Overlaps and other ANDing methods.
thanks, Dave
I think you are looking for an OVER clause. Not sure what the duplicate flag is for though? If you ignore your last three columns, assuming they are computed columns in a query, you could use...
Select
*,
sum(Hrs) over (partition by Emp, Date, Service order by Date)
From (select distinct * from your table) x
If the last three columns are actual columns in your table just replace select * in the derived table with the column names, except those three.

MSSQL - split records per week_start and week_end

I have a table similar to the one represented below.
myID | some data | start_date | end_date
1 Tom 2016-01-01 2016-05-09
2 Mike 2015-03-01 2017-03-09
...
I have a function that when provided with start_date, end_date, interval (for example weeks)
returns me data as below. (splits the start and end dates to week intervals)
select * from my_function('2016-01-01','2016-01-12', 'ww')
2015-12-28 00:00:00.000 | 2016-01-03 00:00:00.000 15W53
2016-01-04 00:00:00.000 | 2016-01-10 00:00:00.000 16W1
2016-01-11 00:00:00.000 | 2016-01-17 00:00:00.000 16W2
I would like to be able to write a query that returns all of the values from the 1 table, but splits Start date and end date in to multiple rows using the function.
myID | some data | Week_start_date | Week_end_date | (optional)week_num
1 Tom 2015-12-28 2016-01-03 15W53
1 Tom 2016-01-04 2016-01-10 16W1
1 Tom 2016-01-11 2016-01-17 16W2
...
2 Mike etc....
Could someone please help me with creating such a query ?
select myID,some_data,b.Week_start_date,b.Week_end_date,b.(optional)week_num from #a cross apply
(select * from my_function('2016-01-01','2016-01-12', 'ww'))b
like sample data i tried
create table #a
(
myID int, some_data varchar(50) , start_date date, end_date date)
insert into #a values
(1,'Tom','2016-01-01','2016-05-09'),
(2,'Mike','2015-03-01','2017-03-09')
here iam keeping function result into one temp table
create table #b
(
a datetime,b datetime, c varchar(50)
)
insert into #b values
('2015-12-28 00:00:00.000','2016-01-03 00:00:00.000','15W53'),
('2016-01-04 00:00:00.000','2016-01-10 00:00:00.000','16W1 '),
('2016-01-11 00:00:00.000','2016-01-17 00:00:00.000','16W2 ')
select myID,some_data,b.a,b.b,b.c from #a cross apply
(select * from #b)b
output like this
myID some_data a b c
1 Tom 2015-12-28 00:00:00.000 2016-01-03 00:00:00.000 15W53
1 Tom 2016-01-04 00:00:00.000 2016-01-10 00:00:00.000 16W1
1 Tom 2016-01-11 00:00:00.000 2016-01-17 00:00:00.000 16W2
2 Mike 2015-12-28 00:00:00.000 2016-01-03 00:00:00.000 15W53
2 Mike 2016-01-04 00:00:00.000 2016-01-10 00:00:00.000 16W1
2 Mike 2016-01-11 00:00:00.000 2016-01-17 00:00:00.000 16W2
Based on your current result and expected result,the only difference ,i see is myID
so you will need to frame your query like this..
;with cte
as
(
select * from my_function('2016-01-01','2016-01-12', 'ww')
)
select dense_rank() over (order by somedata) as col,
* from cte
Dense Rank assigns same values for the same partition and assigs the sequential value to next partition ,unlike Rank
Look here for more info:
https://stackoverflow.com/a/7747342/2975396

How to calculate percentages in tsql using a group by query?

I have a table that lists results by sport and start and end dates and win/loss result. I need to calculate the percentage of wins per sport per season_start. This is my table:
table1
******
id sport won playerid season_start season_end updated_date
--- ----- ---- -------- ------------ ------------ ------------
1 rugby Y kato23 2016-01-01 2016-01-31 2016-02-01
2 rugby Y king54 2016-01-01 2016-01-31 2016-02-01
3 rugby N robby1 2016-03-01 2016-03-28 2016-04-01
4 rugby Y kelly2 2016-03-01 2016-03-28 2016-04-01
5 soccer Y kato23 2016-01-01 2016-01-31 2016-02-01
6 soccer Y jeri44 2016-01-01 2016-01-31 2016-02-01
7 soccer N matt24 2016-06-01 2016-06-30 2016-07-01
8 tennis Y kray43 2016-01-01 2016-01-31 2016-02-01
9 tennis Y jeri44 2016-01-01 2016-01-31 2016-02-01
10 tennis N jeri44 2016-01-01 2016-01-31 2016-02-01
So I'd like to run a query that produces the following result:
sport season_start success_percent
----- ------------ ---------------
rugby 2016-01-01 100.00
rugby 2016-03-01 50.00
soccer 2016-01-01 100.00
soccer 2016-06-01 0.00
tennis 2016-01-01 66.66
I tried :
select sport,won, season_start, count(sport) as sportcount
from table1 where won = 'Y'
group by sport, won, season_start
But this just give me the entire count but not the actual success percent. I tried using case statement but I'm not too good with tsql, or with using 'Sum' to tally the wins and the losses and then calculate the win percentage out of the total.
Can someone provide a tsql query that does this?
You can use conditional counts for this:
select sport, season_start,
sportcount = count(case when won = 'Y' then 'X' end) * 100.0 / count(*)
from table1
group by sport, season_start
Please try the following query:
SELECT sport, season_start,
(CAST(COUNT(CASE won WHEN 'Y' THEN '1' ELSE NULL END) AS DECIMAL(10,2))) / CAST(COUNT(*) AS DECIMAL(10,2)))*100 AS sportcount
FROM table1
GROUP BY sport, season_start
In fact inside the COUNT aggregate function we check the value of won column and if it is equal to 'Y' we will count it otherwise we will ignore it. As you may know Count aggregate function ignore the NULL values, so inside the Count if won is not equal to 'Y' we produce a NULL value that will make the Count to ignore it. After we Count the won counts, we simply need to divide it to total matches count per sport and season(Count(*) will count this).
You have placed won in group by, that will cause problem. Each records with same Groups will be presented in result set just once. If you need to have won in your select list you may try the CROSS APPLY or Window Aggregate Functions. If you need so, please update your question and after that I will update my answer based on it.
Please take note that you may need to CAST or CONVERT the percentage calculation part to decimal or numeric or etc data type if you will need to have the precise result.(This is why I have cast the both Counts to DECIMAL)

query issue - grabbing dates 2 years > current date

I have two tables in a database: 'Events' and 'Days'
Events table has these columns:
ID | Parent_ID
---------------
303| 4
304| -1
305| 3
306| -1
Days table has these columns:
Event_ID | Day
------------------------------------
303 | 2010-06-24 00:00:00.000
304 | 2013-08-21 00:00:00.000
305 | 2011-09-23 00:00:00.000
306 | 2011-12-04 00:00:00.000
303 | 2012-12-24 00:00:00.000
304 | 2010-11-06 00:00:00.000
305 | 2012-03-14 00:00:00.000
306 | 2011-06-12 00:00:00.000
305 | 2010-03-19 00:00:00.000
304 | 2009-01-20 00:00:00.000
What I'm trying to do is, in the Events table, find each ID who has a Parent_ID of -1, then find the same ID listed under Event_ID in the Days table, and return the last date entered IF it is greater than two years from the current date.
So for example, the query should grab 304 and 306 ID from the Events table since they both have -1 for the Parent_ID, and should return:
2013-08-21 00:00:00.000
and
2011-12-04 00:00:00.000
since they are the last entries for the two ID's that are greater than two years from the current date.
Not really sure how to do the greater than two years part. What I have tried is:
select max(day) as day
from Events e join Days d on d.Event_ID = e.ID
where e.Parent_ID = -1
this returns just the latest entry out of all the Event_IDs.
Try the following using GROUP BY HAVING and DATEADD
SQL Fiddle Demo
SELECT
Event_ID,
MAX(Day)
FROM Days
WHERE Event_ID IN (SELECT ID FROM Events WHERE Parent_ID = -1)
GROUP BY Event_ID
HAVING MAX(Day) < DATEADD(dd, -730, getdate())
I guess you are looking for the dates that are 2 years older than current date (if not let me know so that I will update the answer)
where e.Parent_ID = -1 and d.Day < dateadd(day,-730,getdate())

Resources