How to group my table for latest date and ID? - sql

I have a table like this:
I need group this table latest date for every ID.
I mean, I want to get last row every ID. Here is my query:
SELECT DISTINCT ch.Date,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, [Date] from tblCommonHistory ) ch
ON ch.TableIDentity = rk.ID order by ID
How can I do what I want?
EDIT: This query worked for me:
SELECT DISTINCT ch.dt,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, max([Date]) as dt from tblCommonHistory group by TableIdentity) ch ON ch.TableIDentity = rk.ID order by ID

Just use aggregation:
select TableIdentity, max([date])
from tblCommonHistory
group by TableIdentity;
Your question only mentions one table. Your query has two; I don't understand the discrepancy.

It's strange that you have duplicated TableIdentity in tblCommonHistory, but otherwise you should not be getting multiple dates for the same ID from your query.
And also, the only reason to join the 2 tables seems to be that you need to skip those ID that are not present in the tblrisk (is it what you need to do?)
In that case, I'd suggest
SELECT max(ch.Date) AS [Date],ID FROM dbo.tblrisk AS rk
inner join tblCommonHistory AS ch ON ch.TableIDentity = rk.ID
group by ID order by ID

Related

Can we select first row of data from column in sql?

I have a table with multiple data for same ID. I want to get the first row data for the ID.
I have added the below SQL that I have tried.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
LEFT OUTER JOIN "client_details" ON ("client"."id" = "client_details"."client_id")
Since I have multiple address for the same ID, can we get only the first id?
Currently the output I get is 2 rows with different addresses.
You can add to your SQL LIMIT 1 and in case you want to be sure the order you can also add to your SQL ORDER BY...
You can use distinct on:
select distinct on (c.id) c.id, c.company_name, cd.address
from Client c left join
client_details cd
on c.id = cd.client_id
order by c.id, ?;
The ? is for the column that specifies the ordering (the definition of "first"). I am guessing that cd.id is what you want.
Note that this query removes the double quotes and introduces table aliases. This is easier on both the eyes (to read) and the fingers (to type).
use row_number()
select * from
(
SELECT
"client"."id",
"client"."company_name",
"client_details"."address",row_number() over(partition by "client"."id" order by "client_details"."address") as rn
from Client
LEFT OUTER JOIN "client_details" ON "client"."id" = "client_details"."client_id"
)A where rn=1
If there is a field you can order the results by you could use a lateral join e.g.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
left join lateral (
select *
from client_details cd
where cd.client_id = client.id
order by [some_ordering_field]
limit 1
) "client_details" on true

Inner join of table a and table b with selecting only one row of multiple in table b ( row with colum n = max value )

i am a total beginner in SQL. So i have two tables ( table a and table b )
table a holds people with unique IDs, table b holds multiple rows for each person of table a and also the persons ID ( for a possible join ) . the rows in table b are sorted by the columnn row_number.
How can i select all people but only the row of table b with the highest row_number ?
i hope you could somewhat understand me.
Cheers
If i got you right:
SELECT a.persons_ID
,b.rn
FROM A
INNER JOIN
(
SELECT MAX(row_number_column) AS rn
,persons_ID
FROM B
GROUP BY persons_ID
) sub
ON sub.persons_ID = A.persons_ID
The subselect in the inner joins groups your data of table B. So there will be just one row for each persons_ID - the row with the highest row_number_column.
Finally just a simple join on persons_ID.
If you don't need any other information than the person ID and the last row_number per person, then it is quite trivial. Let's call the first table person and the second visit:
select person_id,
max(row_number) max_row_number
from visit
group by person_id
If you need some other information from the first table, like person.name, then perform the join:
select person.person_id,
person.name,
max(visit.row_number) max_row_number
from person
inner join visit on visit.person_id = person.person_id
group by person.person_id,
person.name
If you need some other information from the second table, like visit.present, then modern databases support the row_number() window function (not to be confused with the column that you have):
select name,
base.row_number,
present
from (
select person.name,
row_number() over (partition by visit.person_id
order by visit.row_number desc) rn,
visit.row_number,
visit.present
from person
inner join visit on visit.person_id = person.person_id
) base
where rn = 1
NB: I would strongly advise to rename the column row_number to some other name, as row_number is an analytic function in many databases.

SQL Group By Throwing Up Error (SQL Server)

I have SQL code that throws up an error saying
Error: SQLCODE=-119, SQLSTATE=42803, SQLERRMC=WONUM
The code works fine until I add the group by:
select *
from workorder
left join labtrans on labtrans.refwo=workorder.wonum and labtrans.siteid=workorder.siteid
left join matusetrans on workorder.wonum=matusetrans.refwo and workorder.siteid=matusetrans.tositeid and linetype not in (select value from synonymdomain where domainid='LINETYPE' and maxvalue='TOOL')
left join locations on locations.location = workorder.location and locations.siteid=workorder.siteid
left join person on personid in (select personid from labor where laborcode = labtrans.laborcode)
left join po on workorder.wonum=po.hflwonum and workorder.siteid=po.siteid and workorder.orgid=po.orgid
left join companies on companies.company = po.vendor and companies.orgid=po.orgid
left join pluspcustomer on pluspcustomer.customer=workorder.pluspcustomer
where workorder.wonum='10192'
group by personid
;
if you only GROUP BY personid, you cannot select everything except personid, OR the fields used by aggregate functions such as SUM,MAX, etc
UPDATE
If you just want to see the duplicate personid, you could use:
select personid
from table
group by personid
But be careful here: If you write query like this, the only field that to determine the duplicate records is persionid, if you need to uniquely identify each persionid from different CompanyId, you need to group by persionid, CompanyId, otherwise, same personId from different company will be considered as the duplicate records.
But if you want to delete those duplicate records, you should use ROW_NUMBER()OVER (Partition by persionid Order by your_criteria) to delete the duplicate records. Try to do some searches to see how does that work, usually I prefer to use that function along with the CTE table expression.
if you just need to remove duplicates, use DISTINCT with your query like this:
your query:
SELECT * FROM .....
modify it:
SELECT DISTINCT * FROM .....
Hope it helps.

How to display last updated record for multiple records

I have joined two tables to pull the data I need. I'm having trouble only displaying the most current record from one table. What I'm trying to do is look for the last updated value. I have tried to incorporate max() and row_num but have not had any success.
Here is what I currently have:
select distinct t1.CaId,t1.Enrolled,t1.Plan,t2.Category,t2.updateddate
from table.one(nolock) t1
inner join table.two(nolock) t2 on t1.CaId=t2.CaID
where t1.coverageyear=2016
and right(t1.Plan,2)<>left(t2.Category,2)
order by 5 desc
You can join your main query with a subquery that just grabs the last update date for each ID, like this:
select all_rec.CaId, all_rec.Enrolled, all_rec.[Plan], all_rec.Category, all_rec.updateddate
from
(select distinct t1.CaId,t1.Enrolled,t1.[Plan],t2.Category,t2.updateddate
from [table.one](nolock) t1
inner join [table.two](nolock) t2 on t1.CaId=t2.CaID
where t1.coverageyear=2016
and right(t1.[Plan],2)<>left(t2.Category,2)
) as all_rec
inner join
(SELECT max(updateddate) AS LAST_DATE, CaId
FROM [table.two](nolock)
GROUP BY CaId)
AS GRAB_DATE
on (all_rec.Ca_Id = GRAB_DATE.Ca_Id)
and (all_rec.updateddate = GRAB_DATE.updateddate)
order by 5 desc
I added brackets around your usages of table and Plan because those are SQL reserved words.
If you are trying to get last updated value, then just simply add to your query:
order by t2.updateddate desc
It will show most current record from tables.

Joining two most recent events from two tables

I'm trying to build a report in SQL that shows when a patient last received a particular lab service and the facility at which they've received that service. Unfortunately, the lab procedure and facility are in different tables. Here is what I have now (apologies in advance for my weird aliasing, it makes better since with the actual table names):
;with temp as (Select distinct flow.pid, flow.labdate as obsdate, flow.labvalue as obsvalue
From labstable as flow
Where flow.name = 'lab name'
)
Select distinct p.patientid, MAX(temp.obsdate) [Last Reading], COUNT(temp.obsdate) [Number of Readings],
Case
When count(temp.obsdate) > 2 then 'Active'Else 'Inactive' End [Status], facility.NAME [Facility]
From Patientrecord as p
Join temp on temp.pid = p.PId
Join (Select loc.name, MAX(a.apptstart)[Last appt], a.patientid
From Appointmentstable as a
Join Facility as loc on loc.facilityid = a.FacilityId
Where a.ApptStart = (Select MAX(appointments.apptstart) from Appointments where appointments.patinetId = a.patientid)
Group by loc.NAME, a.patientId
) facility on facility.patientId = p.PatientId
Group by p.PatientId, facility.NAME
Having MAX(temp.obsdate) between DATEADD(yyyy, -1, GETDATE()) and GETDATE()
Order by [Last Reading] asc
My problem with this is that if the patient has been to more than one facility within the time frame, the subquery is selecting each facility into the join, inflating the results by apprx 4000. I need to find a way to select ONLY the VERY MOST RECENT facility from the appointments list, then join it back to the lab. Labs do not have a visitID (that would make too much sense). I'm fairly confident that I'm missing something in either my subquery select or the corresponding join, but after four days I think I need professional help.
Suggestions are much appreciated and please let me know where I can clarify. Thank you in advance!
Change your subquery with alias "facility" to something like this:
...
join (
select patientid, loc_name, last_appt
from (
select patientid, loc_name=loc.name, last_appt=apptstart,
seqnum=row_number() over (partition by patientid order by apptstart desc)
from AppointmentsTable a
inner join Facility loc on loc.facilityid = a.facilityid
) x
where seqnum = 1
) facility
on ...
...
The key difference is the use of the row_number() windowing function. The "partition by" and "order by" clauses guarantee you'll get one set of row numbers per patient and the row with the most recent date will be assigned row number 1. The filter of "seqnum = 1" makes sure you get only the one row you want for each patient.