I have two tables, doc_group and group (also document-table, but that is irrelevant here) and I want to get the latest Group for each Doc ID, based on Created date of the group.
DocID
GroupID
1
1
1
2
2
1
2
3
GroupID
Name
Created
1
Group 1
1.1.2022
2
Group 2
10.10.2022
3
Group 3
2.2.2022
I have tried different approaches, but I cannot get it return the just a single line per DocID.
Here is my latest approach:
SELECT
doc_group.DocID
,doc_group.GroupID
, groups.Created
FROM
doc_group
JOIN
groups
ON groups.ID = (
SELECT
TOP 1 ID
FROM
groups
WHERE
groups.ID = doc_group.GroupID
ORDER BY Created DESC
)
Join and use the row_number function as the following:
SELECT DocID, GroupID, Created
FROM
(
SELECT dg.DocID ,dg.GroupID , g.Created,
ROW_NUMBER() OVER (PARTITION BY dg.DocID ORDER BY g.Created DESC) rn
FROM doc_group dg JOIN groups g
ON dg.GroupID = g.GroupID
) T
WHERE rn = 1
ORDER BY DocID
See demo
Related
I guess this is a standard problem. But I could not find a proper solution yet.
I have three columns in table A:
ID ID_Version Var
1 1 A
1 2 A
1 3 X
1 4 D
2 1 B
2 2 Z
2 3 D
3 1 A
4 1 B
4 2 Q
4 3 Z
For every unique ID, I would like to isolate the Var-value that belongs to the maximal ID-Version.
For ID = 1 this would be D, for ID = 2 this would be D, for ID = 3 this would be A and for ID = 4 this would be Z.
I tried to use a group by statement but I cannot select Var-values when using the max-function on ID-Version and grouping by ID.
Does anyone have a clue how to write fast, effective code for this simple problem?
use row_number() analytic function :
select ID,Var from
(
select row_number() over (partition by id order by id_version desc) as rn,
t.*
from tab t
)
where rn = 1
or max(var) keep (dense_rank...)
select id, max(var) keep (dense_rank first order by id_version desc) as var
from tab
group by id
Demo
You could use ranking function:
SELECT *
FROM (SELECT tab.*, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID_Version DESC) rn
FROM tab)
WHERE rn = 1
Oracle has the keep syntax, so you can also use aggregation:
select id, max(id_version) as id_version,
max(var) keep (dense_rank first order by id_version desc) as var
from a
group by id;
You could also use a simple join to do what you want, see below :
SELECT A.id, A.var FROM A
JOIN
(SELECT id, MAX(id_version) as id_version
FROM A
GROUP BY id) temp ON (temp.id = A.id AND temp.id_version = A.id_version)
Or you could also use a subquery like this :
SELECT a1.id, a1.var FROM A a1
WHERE a1.id_version = (SELECT MAX(id_version) FROM A a2 WHERE a2.id = a1.id)
i have two table showin below
news (table name)
NewsId NewsDate
1 25-03-2014
2 29-03-2014
newsImageGal (table name)
newsSr newsId newsImages
1 1 images/i.jpg
2 1 images/j.jpg
3 1 images/k.jpg
4 2 images/l.jpg
5 2 images/m.jpg
6 2 images/n.jpg
i want a result like
NewsId NewsDate newsId newsImages
1 25-03-2014 1 images/i.jpg
2 9-03-2014 2 images/l.jpg
i have tried using join query and group by function but it shows duplicate multiple records how to solve this query?
You can write as
;WITH CTE AS
( SELECT N.NewsId
,N.NewsDate
,NIG.newsImages
,ROW_NUMBER() OVER (PARTITION BY N.NewsId ORDER BY NIG.newsSr ASC)
AS rownum
FROM news N
JOIN newsImageGal NIG ON N.NewsId = NIG.newsId
)
SELECT NewsId,
NewsDate,
newsImages
FROM CTE
WHERE rownum = 1
Try this.
SELECT a.NewsId,
a.NewsDate,
b.newsImages
FROM news a
JOIN (SELECT Row_number()OVER(partition BY newsid ORDER BY newssr) rn,
*
FROM newsImageGal) b
ON a.NewsId = b.newsId
WHERE rn = 1
Key here is to find the first image that got added into newsImageGal table per newsid.
so use the window function to create Row_number per newsid in order of newsSr.
SELECT Row_number()OVER(partition BY newsid ORDER BY newssr) rn,
*
FROM newsImageGal
From the above query you can see the rn=1 is the first image that got added into the newsImageGal join the result with news table and filter the result with rn=1
can you try this
select distinct ng.newsId, ng.newsImages
from (
select MIN(newsSr),newsId,newsImages
from newsImageGal
group by newsId,newsImages) ng
join news ne
on ne.newsId=ng.newsId
select n.NewsId,n.NewsDate,g.newsImages
from news n
join newsImageGal g on n.NewsId=g.newsSr
SELECT n.NewsId,
n.NewsDate,
ng.newsId,
ng.newsimages
FROM news n,
(SELECT *,
Rank()OVER(PARTITION BY newsId ORDER BY newsSr DESC) AS rank
FROM newsImageGal) ng
WHERE n.NewsId = ng.newsId
AND rank = 1
I have two tables linked by an AUTO_KEY field, from one table I'm retrieving the number (id), from the other I get several statuses by number(id), each status has a date associated to it.
I need to restrict the results only to the maximum/latest date for all numbers(ids) and the corresponding status
SELECT
OPERATION.NUMBER,
STATUS.STATUS,
Max(STATUS.DATE)
FROM
STATUS,
OPERATION
WHERE
OPERATION.AUTO_KEY = STATUS.AUTO_KEY
From here
Number Status Date
-----------------------------
1 A 10/20/13
1 B 10/15/13
2 A 10/10/13
2 AX 10/05/13
2 AD 10/03/13
3 DD 10/03/13
The outcome should be
Number Status Date
-----------------------------
1 A 10/20/13
2 A 10/10/13
3 DD 10/03/13
Thanks in advance
You can use a CTE with ROW_NUMBER() function. Also Please use a Table JOIN instead FROM STATUS, OPERATION
;With CTE AS (
SELECT O.NUMBER, S.STATUS, S.DATE,
ROW_NUMBER() OVER (ORDER BY S.DATE DESC) RN
FROM STATUS S JOIN OPERATION O
ON O.AUTO_KEY = S.AUTO_KEY
)
SELECT NUMBER, STATUS, DATE
FROM CTE
WHERE RN = 1
ORDER BY NUMBER
SELECT OPERATION.CNUMBER,
STATUS.STATUS,
STATUS.CDATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
AND STATUS.CDATE = (
SELECT MAX(STATUS.CDATE) MAX_DATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
GROUP BY OPERATION.CNUMBER )
I have a table of election results for multiple nominees and polls. I need to determine which nominee had the most votes for each poll.
Here's a sample of the data in the table:
PollID NomineeID Votes
1 1 108
1 2 145
1 3 4
2 1 10
2 2 41
2 3 0
I'd appreciate any suggestions or help anyone can offer me.
This will match the highest, and will also bring back ties.
select sd.*
from sampleData sd
inner join (
select PollID, max(votes) as MaxVotes
from sampleData
group by PollID
) x on
sd.PollID = x.PollID and
sd.Votes = x.MaxVotes
SELECT
t.NomineeID,
t.PollID
FROM
( SELECT
NomineeID,
PollID,
RANK() OVER (PARTITION BY i.PollID ORDER BY i.Votes DESC) AS Rank
FROM SampleData i) t
WHERE
t.Rank = 1
SELECT PollID, NomineeID, Votes
FROM
table AS ABB2
JOIN
(SELECT PollID, MAX(Votes) AS most_votes
FROM table) AS ABB1 ON ABB1.PollID = ABB2.PollID AND ABB1.most_votes = ABB2.Votes
Please note, if you have 2 nominees with the same number of most votes for the same poll, they'll both be pulled using this query
select Pollid, Nomineeid, Votes from Poll_table
where Votes in (
select max(Votes) from Poll_table
group by Pollid
);
I have a query that is designed to find the number of people who went to a hospital more than once. What I have works, but is there a way to do it without the subquery?
SELECT count(*) as counts, hospitals.hospitalname
FROM Patient INNER JOIN
hospitals ON Patient.hospitalnpi = hospitals.npi
WHERE (hospitals.hospitalname = 'X')
group by patientid, hospitalname
having count(patient.patientid) >1
order by count(*) desc
This will always return the number of correct rows (30), but not the number 30. If I remove the group by patientid then I get the entire result set returned.
I solved this problem by doing
select COUNT(*),hospitalname
from
(
SELECT count(*) as counts,hospitals.hospitalname
FROM hospitals INNER JOIN
Patient ON hospitals.npi = Patient.hospitalnpi
group by patientid, hospitals.hospitalname
having count(patient.patientid) >1
) t
group by t.hospitalname
order by t.hospitalname desc
I feel that there has to be a more elegant solution than using subqueries all the time. How could this be improved?
sample data from first query
row # revisits
1 2
2 2
3 2
4 2
same data from second, working query
row# hosp. name revisitAggregate
1 x 30
2 y 15
3 z 5
Simple one-to-many relationship between patient and hospitals
It's super hacky, but here you are:
SELECT TOP 1
ROW_NUMBER() OVER (order by patient.patientid) as Count
FROM
Patient
INNER JOIN hospitals
ON Patient.hospitalnpi = hospitals.npi
WHERE
(hospitals.hospitalname = 'X')
GROUP BY
patientid,
hospitalname
HAVING
count(patient.patientid) >1
ORDER BY
Count desc
select distinct hospitalname, count(*) over (partition by hospitalname) from (
SELECT hospitalname, count(*) over (partition by patientid,
hospitals.hospitalname) as counter
FROM hospitals INNER JOIN
Patient ON hospitals.npi = Patient.hospitalnpi
WHERE (hospitals.hospitalname = 'X')
) Z
where counter > 1