Window function in SQL - sql

I'm trying to get the column 'Desired Result' from the data presented. I'm not sure of the correct syntax for the windows function to do this. I've tried row_number and versions of RANK but just can seem to get it correct. Any help would be appreciated. thanks
ID TransactionID Desired Result
33 2681998458900 1
44 2682232081872 1
44 2682232081872 1
44 2682232081872 1
44 2683269923140 2
44 2683269923140 2
44 2683269923140 2
60 2345620067722 1

Select ID, TransactionID, Dense_rank() over (partition by ID order by transactionID)
Rank
from table1
This would give your expected results. Dense rank will not skip ranking and will give the same rank if the ordering column has the same value.

Related

Sql getting MAX and MIN values based on two columns for the ids from two others

I'm having difficulties figuring a query out, would someone be able to assist me with this?
Problem: 4 columns that represent results for the 2 separate tests. One of them taken in UK and another in US. Both of them are the same test and I need to find the highest and lowest score for the test taken in both countries. I also need to avoid using subqueries and temporary tables. Would appreciate theoretical ideas and actual solutions for the problem.
The table looks like this:
ResultID Test_UK Test_US Test_UK_Score Test_US_Score
1 1 2 48 11
2 4 1 21 24
3 3 1 55 71
4 5 6 18 78
5 7 4 19 49
6 1 3 23 69
7 5 2 98 35
8 6 7 41 47
The desired results I'm looking for:
TestID HighestScore LowestScore
1 71 23
2 35 11
3 69 55
4 49 21
5 98 18
6 78 41
7 47 19
I tried implementing a case of comparison, but I still ended up with subquery to pull out the final results. Also tried union, but it ends up in a sub query again. As far as I can think it shoul be a case when then query, but can't really come up with the logic for it, as it requires to match the ID's of the tests.
Thank you!
What I've tried and got the best results (still wrong)
select v.TestID,
max(case when Test_US_Score > Test_UK_Score then Test_UK_Score else null end) MaxS,
min(case when Test_UK_Score > Test_US_Score then Test_US_Score else null end) MinS
FROM ResultsDB rDB CROSS APPLY
(VALUES (Test_UK, 1), (Test_US, 0)
) V(testID, amount)
GROUP BY v.TestID
Extra
The answer provided by M. Kanarkowski is a perfect solution. I'm no expert on CTE, and a bit confused, how would it be possible to adapt this query to return the result ID of the row that min and max were found.
something like this:
TestID Result_ID_Max Result_ID_Min
1 3 6
2 7 1
3 6 3
Extra 2
The desired results of the query would me something like this.
The two last columns represent the IDs of the rows from the original table where the max and min values were found.
TestID HighestScore LowestScore Result_ID_Of_Max Result_ID_Of_Min
1 71 23 3 6
2 35 11 7 1
3 69 55 6 3
For example you can use union to have results from both countries togehter and then just pick the maximum and the minimum for your data.
with cte as (
select Test_UK as TestID, Test_UK_Score as score from yourTable
union all
select Test_US as TestID, Test_US_Score as score from yourTable
)
select
TestID
,max(score) as HighestScore
,min(score) as LowestScore
from cte
group by TestID
order by TestID
Extra:
I assumed that you want to have the additional column with the previous result. If not just take the above select and replace Test_UK_Score and Test_US_Score with ResultID.
with cte as (
select Test_UK as TestID, Test_UK_Score as score, ResultID from yourTable
union all
select Test_US as TestID, Test_US_Score as score, ResultID from yourTable
)
select
TestID
,max(score) as HighestScore
,min(score) as LowestScore
,max(ResultID) as Result_ID_Max
,min(ResultID) as Result_ID_Min
from cte
group by TestID
order by TestID

Calculate moving average with null values

I have a school graduation data set by year and subgroup and have been provided the numerator and denominator and the single year graduation rate but I also need to calculate a 3 year moving average. I was advised by a statistician that no longer works with us that to do this I needed to get the running total for the numerator for 3 years and the running total for 3 years for the denominator. I understand the math behind it and have checked my work by hand and via excel with a few subgroups. I have also calculated this using T-SQL with no problem so long as there are no null records but I’m struggling with the calculation when there are nulls or 0.
I have tried running the query accounting for null by using NULLIF
ID,
Bldg,
GradClass,
Sbgrp ,
TGrads,
TStus,
Rate,
/*Numerator Running total*/
SUM (TGrads) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) AS NumSum,
/*Denominator Running Total*/
SUM ( TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) AS DenSum,
/*Moving Year Average*/
(
( SUM ( TGrads) OVER ( partition BY DistrictID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ) / NULLIF ( ( SUM ( TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ), 0 ) * 100
) AS 3yrAvg
FROM
KResults.DGSRGradBldg
First question, I was provided a record for all subgroups even if they didn’t have students in the subgroup. I want to keep the record so that all subgroups are accounted for within the district and since I know that they didn’t have data, can I substitute the Null values in Tgrads, TStus with a 0? If I do substitute those values with a 0 how can I show the rate as null?
Second question how can I compute the rate with either a null or 0 denominator? I understand you can’t divide by 0 but I want to maintain the record so it’s easy and clear to see that they had no data. How can I do this? When I try to calculate this without accounting for Null I get errors, 1.)Divide by zero error encountered. (8134) and 2.) Null value is eliminated by an aggregate or other SET operation. (8153).
Knowing I can’t divide by 0 or Null I modified my query to include NULLIF and when I do that the query runs with no errors but I don’t get accurate percentage for rates that are below 100%. All my rates are now either 100% or 0 - note the last row, the moving average of 2/3 is not 0.
Here’s what the data looks like if I try to account for nulls my Moving three year average shows as 0. Note the Moving three year Avg Column shows all 0.
ID Bldg Class Sbggrp TGrads TStus Rate NumSum DenSum 3yrAvg
A 1 2014 A1 46 49 93.9 46 49 0
A 1 2015 A1 41 46 89.1 87 95 0
A 1 2016 A1 47 49 95.9 134 144 0
A 1 2017 A1 38 40 95.0 126 135 0
A 1 2018 A1 59 59 98.3 143 148 0
A 1 2014 A2 1 1 100 1 1 100
A 1 2015 A2 1 1 100
A 1 2016 A2 1 1 100
A 1 2017 A2 2 3 66.7 2 3 0
A 1 2018 A2 2 2 100 4 5 0
Any advice would be appreciated but please provide suggestions kindly to this newbie.
Thanks for your time and help.
Answer to question 1: put in the select condition
ISNULL(TGrads,0) AS TGRADS,
ISNULL(TStus,0) AS TSTUS,
Answer to question 2: I'd do this
(CASE WHEN SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) IS NOT NULL
AND SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) <>0
THEN (SUM(TGrads) OVER ( partition BY DistrictID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) / (SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ) ) * 100
ELSE NULL END
) AS 3yrAvg
I put null after "ELSE"...You can choose your default value.

How to sort top 4 values with SQL Server which contains negative numbers

Input file
SN ID
------------
1 55
2 -25
3 62
4 -0.05
5 0.0
Output file should be after sorting
SN ID
-------
3 62
1 55
5 0.0
4 -0.05
2 -25
Using this SQL Server command need to modify by logic
select top 4 *
from filename
order by ID desc
It sounds as though perhaps your ID column is actually some sort of text, rather than numeric, type. If so, then casting the column to a decimal and then sorting should fix the problem:
SELECT TOP 4 *
FROM filename
ORDER BY CAST(ID AS DECIMAL(10,4)) DESC;
Note that if the above query does work, then you should seriously consider not storing numeric information as text.
You are missing a WHERE clause. If you need to filter only by negative values just add the following:
select top 4 *
from filename
where ID < 0
order by ID desc

Grouping of values in sql

My dataset looks like this:
Id MaxSpeed Distance
1 112 33
1 89 56
2 100 34
3 125 10
For each Id, I need to set up the count as 1.
Output has to be
Id count
1 1
2 1
3 1
I tried with group by on Id, it does not fetch me this result.
Any help would be really appreciated !!
Perhaps you are overthinking it.
Select Distinct ID,1 as Count From YourTable
Does the count always need to be 1? If so, could this query work?
SELECT DISTINCT ID, 1
FROM your_table;
Try following sql code:
Select distinct Id,1 as count From Table_Name;

MSSQL - Grouping Results using MAX()

I have this dataset;
dID Num
11 3
11 4
11 5
13 9
13 11
45 3
45 8
99 44
99 78
99 53
I want it to look like this.
dID Num
11 5
13 11
45 8
99 78
List all ID's and only show those ID's where the 'Num' is the Largest number for that group of ID's
my attempt here doesnt quite work out.
http://sqlfiddle.com/#!9/1a47f/1
You seem to just want an aggregation query:
select dId, max(num) as num
from data t
group by dId;
You need to aggregate by the first column, not the argument to the aggregation function.
If you have oversimplified the problem, and want other columns as well, then use row_number():
select t.*
from (select t.*, row_number() over (order by num desc) as seqnum
from data t
) t
where seqnum = 1;
You almost get it right, you just grouped by the wrong column:
select dID,
MAX(num) from data
group by dID
See it here: http://sqlfiddle.com/#!9/1a47f/3