How to get value from another row in SQL?
ID DeletedPersonID ProductKey PartyID RespID
9 461 17 33 95
10 95 17 34 95
and I have this select statement
select
drp.ID,
drp.DeletedPersonID,
drp.ProductID,
case when drp.DeletedPersonID != drp.RespID then (Get Party Key by RespID) else drp.PartyID end as 'PartyID',
case when drp.DeletedPersonID != drp.RespID then (Get Party Key by RespID) else drp.PartyName end as 'PartyName',
case when drp.DeletedPersonID = drp.RespID then null else drp.PartyID end as 'SubPartyID',
from dbo.RespHistory drp
In above example since ID = 10 has the same DeletedPersonID and RespID value I like to use the same PartyID but in ID = 9 or in the first line Since DeletedPersonID and RespID are difference I want to use PartyID of ID = 10
I am looking a view similar to shown below
ID DeletedPersonID ProductKey PartyID PartyName SubPartyID
9 461 17 34 ABC 33
10 95 17 34 XYZ null
Something like this
with equals_cte (RespID) as (
select RespID
from dbo.RespHistory
where DeletedPersonID = RespID
)
select
drp.ID, drp.DeletedPersonID, drp.ProductKey, coalesce(ec.RespID, drp.RespID) PartyID
, drp.PartyName, drp.RespID
, iif(drp.DeletedPersonID = drp.RespID, null, drp.RespID) SubPartyID
from dbo.RespHistory drp
left join equals_cte ec on drp.RespID = ec.RespID;
Related
ID Date Value Average
1 10/5/2017 15 15
2 10/6/2017 25 20
3 10/7/2017 35 25
4 10/8/2017 45 35
5 10/9/2017 55 45
6 10/10/2017 65 55
7 10/11/2017 75 65
If this is my table, I want average to be a computed column and its formula in general is average of previous 3 row's Value column.
(Ex. for 2nd row it is (25+15)/2 )
How can i do such a thing in computed column? Is there any better way to achieve this.
Thanks in advance.
i would go with a view and use avg windows function
select
id,
date,
value,
avg(value) over (order by id)
from table
Updated answer: you could use frames clause like below
Working Demo
;with cte(id,date,val)
as
(
select 1 ,'10/5/2017' , 15 UNION ALL
select 2 ,'10/6/2017' , 25 UNION ALL
select 3 ,'10/7/2017' , 35 UNION ALL
select 4 ,'10/8/2017' , 45 UNION ALL
select 5 ,'10/9/2017' , 55 UNION ALL
select 6 ,'10/10/2017', 65 UNION ALL
select 7 ,'10/11/2017', 75
)
SELECT *,avg(VAL) OVER (ORDER BY id rows between 2 PRECEDING and current row ) FROM CTE
I have this table.
ID Date Value
___ ____ _____
3241 9/17/12 5
3241 9/16/12 100
3241 9/15/12 20
4355 9/16/12 12
4355 9/15/12 132
4355 9/14/12 4
1001 NULL 89
1001 9/16/12 125
5555 NULL 89
1234 9/16/12 45
2236 9/15/12 128
2236 9/14/12 323
2002 9/17/12 45
I would like to select the maximum date grouped by id and including NULL as maximum value that should be in the result to get something like that.
ID Date Value
___ ____ _____
3241 9/17/12 5
4355 9/16/12 12
1001 9/16/12 125
5555 NULL 89
1234 9/16/12 45
2236 9/15/12 128
2002 9/17/12 45
I found a solution but that not include NULL as maximum value
the solution by #bluefeet
Return value at max date for a particular id
SELECT t1.id,
t2.mxdate,
t1.value
FROM yourtable t1
INNER JOIN
( SELECT max(date) mxdate,
id
FROM yourtable
GROUP BY id) t2 ON t1.id = t2.id
AND t1.date = t2.mxdate
I also search for a solution to see how can we select NULL maximum value in t-sql so i found this solution by #Damien_The_Unbeliever How can I include null values in a MIN or MAX?
SELECT recordid,
MIN(startdate),
CASE
WHEN MAX(CASE
WHEN enddate IS NULL THEN 1
ELSE 0
END) = 0 THEN MAX(enddate)
END
FROM tmp
GROUP BY recordid
But i m stuck i don't know how to merge between this two solution to get what i want.
PS: I m using SQL SERVER 2008
You can use this
SELECT
ID
,[Date]
,[Value]
FROM(
SELECT
*
, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ISNULL([Date],'9999-12-31') DESC) AS Row#
FROM yourtable
) A WHERE Row# = 1
I have a table that looks as follows:
DepartmentID DepartmentTierID AllDepartmentTierID
----------------------------------------------------
1 NULL 25
1 26 26
1 NULL 27
2 NULL 28
2 NULL 29
2 30 30
3 NULL 31
3 NULL 32
3 NULL 33
If there is a value in the DepartmentTierID in any of the records for a specific DepartmentID, I need to return all the AlldepartmentTierIDs for that department. If there is no DepartmentTierID for a specific DepartmentID no AllDepartmentTiersIDs should return.
In other words, DepartmentID 1 would return 25,26 and 27. DepartmentID 2 would return 28,29 and 30 and and DepartmentID 3 wuld return nothing.
The resulting dataset should look as follows:
AllDepartmentTierID
-------------------
25
26
27
28
29
30
Thanks in advance.
You can use WHERE EXISTS for this:
Select AllDepartmentTierId
From YourTable T1
Where Exists
(
Select *
From YourTable T2
Where T1.DepartmentId = T1.DepartmentId
And T2.DepartmentTierId Is Not Null
)
You can use EXISTS:
SELECT A.AllDepartmentTierID
FROM dbo.YourTable A
WHERE EXISTS(SELECT 1 FROM dbo.YourTable
WHERE DepartmentID = A.DepartmentID
AND DepartmentTierID IS NOT NULL);
One way is using window function:
select
AllDepartmentTierID
from (
select
AllDepartmentTierID,
max(DepartmentTierID) over (partition by DepartmentID) x
from t
) t where x is not null;
Here is one way using Count() Over() window aggregate function.
Select * from
(
select *,count(DepartmentTierID) over(partition by DepartmentID) as cnt from yourtable
) A
Where cnt >= 1
How it works
Count aggregate will not count NULL values so when count is greater than one it means the DepartmentID is having atleast one not null DepartmentTierID
You would want to do something like this. Please check, this was not tested.
SELECT AllDepartmentTierID
FROM Department
WHERE DepartmentID IN(
SELECT DepartmentID
FROM Department d
WHERE d.DepartmentTierID <> NULL)
I have a table as following:
[ID] [Name] [Score] [Class]
1 John 90 A
2 Mary 63 A
3 Tom 87 A
4 David 98 A
5 Mary 87 B
6 David 77 B
7 David 73 C
8 Mary 92 C
9 Tom 73 C
10 John 79 C
11 Mary 70 D
12 Jane 85 D
13 David 83 D
I need to get the top 2 persons based on the scores in each class.
My expected output is
[ID] [Name] [Score] [Class]
1 John 90 A
4 David 98 A
5 Mary 87 B
6 David 77 B
8 Mary 92 C
10 John 79 C
12 Jane 85 D
13 David 83 D
Here is what I tried so far but this is not producing the correct results
SELECT *
FROM Student s
WHERE
(
SELECT COUNT(*)
FROM Student f
WHERE f.name = s.name AND
f.score >= s.score
) <= 2
Use ROW_NUMBER:
SELECT
ID, Name, Score, Class
FROM(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Class ORDER BY Score DESC)
FROM Student
) t
WHERE rn <= 2
DEMO
The specification said... "for each class"
The smallest change that would need to be made to the proposed query to get the the specified results "students with the two highest scores for each class", we'd need to replace one of the predicates in the correlated subquery... matching on [class] rather than on [name]...
SELECT s.*
FROM Student s
WHERE
(
SELECT COUNT(*)
FROM Student f
WHERE f.class = s.class
AND f.score >= s.score
) <= 2
Note that if there are multiple students in the class with the same "highest scores", the query will return all of those students, not just two students for class.
If we specifically want to return "at most two students from each class, the students who have the highest score in each class", we'd need to write the query a little differently.
Given the example data, with no duplicate scores in a class, the results would be the same.
The difference can be demonstrated by adding a row to the example data, for example, adding Saul, having the same "second highest" score as David.
11 Mary 70 D
12 Jane 85 D
13 David 83 D
14 Saul 83 D
The question we need to ask about the specification... should only two students be returned for this class, Jane has the highest score, so obviously return Jane. But David and Saul have the same score. Do we return both, or if we only return one of them, does it matter which one we return?
Should we return three rows:
[ID] [Name] [Score] [Class]
12 Jane 85 D
13 David 83 D
14 Saul 83 D
because those are all of the students with the two highest scores, or should we return just two of the students with the highest scores:
[ID] [Name] [Score] [Class]
12 Jane 85 D
13 David 83 D
or
[ID] [Name] [Score] [Class]
12 Jane 85 D
14 Saul 83 D
Once that question is answered, we can write a query that returns the specified result.
And (obviously) this isn't the only query. There are other query patterns that will return an equivalent result... using either ANSI-standard syntax, or vendor specific extensions.
I want to number some base rows in table without mixing the ordering. I have table like this:
Status ProductId
A 12
NULL 25
B 35
C 56
NULL 89
NULL 99
D 120
E 140
I want to add No column, to count Statuses which is not null with same ProductId ordering, but, don't want to count NULL rows. I want the result like this:
No Status ProductId
1 A 12
NULL 25
2 B 35
3 C 56
NULL 89
NULL 99
4 D 120
5 E 140
I work on SQL Sever 2008, SSRS. Someone can give solution in SQL side or in RDL file.
You can do this:
WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY Status) AS No,
Status, ProductId
FROM table1
WHERE Status IS NOT NULL
)
SELECT
c.No,
t.Status,
t.ProductId
FROM table1 AS t
LEFT JOIN CTE AS c ON c.ProductId = t.ProductId
ORDER BY ProductId;
SQL Fiddle Demo
You can use this query directly in your report.