How to select max date value while selecting max value - postgresql

I have the following sample from a table with students results with date for a school entry exam
First student passed exam - This is the most common record found for most students
Second student failed 1st time entry and passed second time based on the date
3rd student had a failed input entry and was corrected based on the Version
I need the results to like like the picture above, so we take into regard using the latest date and highest version!
My basic query thus far is
select studentid
,examdate --(Date)
,result -- (charvar)
from StudentEntryExam
How should I approach this issue?

demo:db<>fiddle
SELECT DISTINCT ON (studentid)
*
FROM mytable
ORDER BY studentid, examdate DESC, version DESC
DISTINCT ON returns the first record of an ordered group. In that case the groups are the studentids. You must find the correct order to set the required record first. So, you need to order by studentid, of course. Then you need the most recent examdate first, which can be achieved with DESC order. If there are two records on the same date, you need to order the highest version first as well using the DESC modifier, too.

Related

I have a delta in specific records in same table - how do I find that specific row?

I have a table A which contains list of counties for a given year along with other records.
Columns are 'Year' and 'CountyName'.
For 2020, there are 6434 'Counties' listed and for 2019, 6433 'Counties' are listed (in the same table).
How do I find the CountyName that is missing in 2019?
I can ofcourse run a simple query to get these records individually and then find out the missing county but I am trying to check if it can be done at the query level.
Thank you.
You can easily achieve it with the usage of the not in function or the exist one.
Something like:
Select countryname from table where year =2019 and countryname not in (Select countryname from table where year =2020)

Trying to select second oldest record for each customer and group them by month shipped

I'm trying to create a report which picks 2nd oldest order for every user and groups them by month/year. I know how to select the oldest order for each, but can't figure out how to get the second oldest.
The input data is a table which has every customers' order as a single row with the relevant columns being
order.id, order.user_id, order.date, product.name...
The ideal result I'm looking for is something like:
mon/year : number of second orders
12/2013 : 14
01/2014 : 2
Try this Code
select to_char(date_trunc('month',date),'MM/yyyy'),(select count(*) from order where date=min(p.date)) from order p
group by date_trunc('month',date)

Greatest n per group with multiple criteria for greatest

I need to select the largest, most recent or currently active term across a number of schools, with the assumption that is possible for a school to have multiple concurrent terms (ie, one term that honors students are registered in, and another for non honors). Also need to take into account the end date, as the honors term may have the same start date but may be year long instead of just a semester, and I want the semester.
Code looks something like this:
SELECT t.school_id, t.term_id, COUNT(s.id) AS size, t.start_date, t.end_date
FROM term t
INNER JOIN students s ON t.term_id = s.term_id
WHERE t.school_id = (some school id)
GROUP BY t.school_id, t.term_id
ORDER BY t.start_date DESC, t.end_date ASC, size DESC LIMIT 1;
This works perfectly to find the largest currently or most recently active term, but I want to be able to eliminate the WHERE t.school_id = (some school id) part.
A standard greatest n per group can easily choose the largest OR most recent term, but I need to select the most recent term that ends soonest with the largest number of students.
Not sure I am interpreting your question correctly. Would be easier if you had supplied table definitions including primary and foreign keys.
If you want the the most recent term that ends soonest with the largest number of students per school, this might do it:
SELECT DISTINCT ON (t.school_id)
t.school_id, t.term_id, s.size, t.start_date, t.end_date
FROM term t
JOIN (
SELECT term_id, COUNT(s.id) AS size
FROM students
GROUP BY term_id
) s USING (term_id)
ORDER BY t.school_id, t.start_date DESC, t.end_date, size DESC;
More explanation for DISTINCT ON in this related answer:
Select first row in each GROUP BY group?

SQL Reporting Services, filtering on Field not in DISTINCT SELECT statement?

I am using MS SQL Report Builder 3.0 to generate a report for SQL Reporting Services. I have a dataset that includes the columns AppointmentDate, PatientID, and InsuranceCarrier. I want to find out the number of DISTINCT patients that visited within a certain timeframe (begining AppointmentDate to ending AppointmentDate). The only time a patient should be present more than once in the query is if they had a different insurance carrier on a repeat visit.
If I perform the following query:
SELECT DISTINCT AppointmentDate, PaientID, InsuranceCarrier
FROM Encounters
WHERE AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
Then I get a list of each patient and insurance carrier that visited in that date range. Unfortunately, since each AppointmentDate is also distinct, the Patients get duplicated for each individual appointment date. For example, if Patient X shows up twice in that timeframe specified, it will show both appointments.
If I remove the AppointmentDate from my SELECT statement, then under Dataset properties in the Report Builder 3.0 I can no longer Filter based on the AppointmentDate expression. I could do my filtering directly in the WHERE clause of the T-SQL statement, but that means I cannot use the run-time Report Parameters input by the user. This is a problem because I am filtering based on Report Parameters that the user selects when running the report. They input the starting AppointmentDate and a "18-months prior" Parameter is calculated as the beginning and end AppointmentDates to filter against.
So how do I include the AppointmentDate so that I can filter with it, but not include it in my DISTINCT SELECT so that it properly DISTINCTifies my data.
#FreefallGeek,
What do you mean by you can't filter AppointmentDate if you remove it from SELECT? Report Builder allows you do dataset filtering based on the user assigned parameter in run time with query like this,
SELECT DISTINCT PaientID, InsuranceCarrier
FROM Encounters
WHERE
AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
With #beginningofdaterange and #endofdaterange as your report parameter. This should work unless you need to do additional filtering that require to return AppointmentDate as result.
If you really need to return the Appointment date as result or for additional filtering, then the next question is what should be the AppointmentDate when there are multiple visit with same patient and insurance carrier? The first visit or the last visit within the date range? If that is the case, you could use group by like this for first visit,
SELECT Min(AppointmentDate) AS FirstAppointmentDate, PaientID, InsuranceCarrier
FROM Encounters
WHERE
AppointmentDate >= #beginningofdaterange
AND AppointmentDate <= #endofdaterange
GROUP BY PaientID, InsuranceCarrier
ORDER BY AppointmentDate
However, from your description, it appears that you only need the distinct patient and insurance carrier with the capability to filter the date. If that understanding is correct, you could just filter the appointment with user input parameter in the WHERE clause without the SELECT.
In this particular case, I would take into account all visits per the entire day. And instead of displaying multiple encounters per patient per day, I would go to display for the report as AppointmentDate only the day part of the AppointmentDate itself. As the filtering might not need the exact moment of the visit, but only the fact that it took place. The resulting set would be then filtered by the report.
Your particular select would look like the following:
-- small modification (take encounters by entire day):
SELECT DISTINCT
CAST(e.AppointmentDate as Date) as AppointmentDateDay, -- the day of the visit
e.PatientID,
e.InsuranceCarrier,
COUNT(e.Id) as CntVisits -- display them if you'd like
FROM Encounters as e
WHERE AppointmentDate >= '20130624 10:00:00'
AND AppointmentDate <= '20130625 18:00:00'
GROUP BY PatientID, InsuranceCarrier, CAST(e.AppointmentDate as Date)
ORDER BY PatientId;
Example Fiddle - see both result sets.
If you really need to show the entire AppointmentDate to the user, I admit I don't have an idea now.

Sql GroupBy with one more field in the result set as in the group by clause

I have a table with different offers which are bound to a specific date. depended on the date the price changes. i want to get the cheapest deal for each date.
my problem is i use a group by like:
select price, date from deals group by date, price
to display the offer, i need more records which are not in the group by clause. the best field would be my autoid, so if a customer selects a offer with a specific price i can display this offer with all its fields using a second select.
i hope this makes it simpler to answer my question. i tried to keep it generic as possible but i have the feeling it was not described clear enough :-)
Just add the Id column into the GROUP BY list
SELECT id, date, price
FROM products
GROUP BY id, date, price
Otherwise Sql Server was not able identify which id is to return for grouped by price and date rows, for instance consider two following rows:
1 | 10-10-2010 | 100 |
2 | 10-10-2010 | 100 |
Which Id value should be selected for row which is grouped by date and price?
??? | 10-10-2010 | 100 |
You either need to specify an aggregate function on ID or add it to your group by clause like #sll suggested. Aggregate example:
SELECT MAX(id), date, price
FROM products
GROUP BY date, price
If you remove the id from Select clause, you will have a list of all distinct couples of date and price.
If you add the id to the Group By clause, since it is an identity, you will obtain a row per every record in your table, so that your Group By clause won't be useful.
The third way is to use an aggregate function on id in the Select clause to obtain one value for every single group (the first, the min, the max, etc.).
Hi Group by is useful when you are doing count etc.
SELECT [Display Billing Provider], [Display Insurance Category]
, SUM([TOTAL RVUs]) AS RVUs_08
, SUM([Units]) AS Units_08
, SUM(Payments) AS Payments_08
FROM dbo.ProductivityAnal_2008
GROUP BY [Display Billing Provider],[Display Insurance Category]
ORDER BY [Display Billing Provider],[Display Insurance Category]
Thanks Abe