Querying a table for a minimum based on the largest of a second column - sql

I have a subquery that has the following
PreviousRateCode, CurrentRateCode, PreviousReportDate, CurrentReportDate, TransactionDate.
The data in my subquery looks like
How can I query the results below to get the Smallest "RecentDerogMonths" based on the Largest "WorstDerogLevel" ?
There's an additional column that I omitted that has a customerID, so I need the Smallest "RecentDerogMonths" based on the Largest "WorstDerogLevel" for each customer, and this is a subquery of a larger select, so what I need is something like
Select Lowest Months by highest level
From (The result above)
Group by CustomerID

Is this what you want?
select top 1 t.*
from t
order by WorstDerogLevel desc, RecentDerogMonths asc;
If you want all matching rows that meet the condition then use select top (1) with ties.
EDIT:
Per customer, you use window functions. One method uses a subquery, but here is a cool trick:
select top (1) with ties t.*
from t
order by row_number() over (partition by customerid order by WorstDerogLevel desc, RecentDerogMonths asc);

Related

How to pick first record from the duplicates, With only duplicate column values

Here is the situation where I have a table in bigquery like following.
As in the table we have record 1 and 3 with the same id but different first_name (Say the person with the id one changed his first_name) all other fields are same in both of the records (1 and 3) Now I need to select one records out of those 2 how can I do that. I tried self join but that is discarding both of the records, group_by will not work because the records is not duplicate only the Id is duplicate same with the distinct.
Thanks!!!!
The query I am using right now is
select * from table t group by 1,2,3,4,5;
You Can use ROW_NUMBER function to assign row numbers to each of your records in the table.
select *
from(
select *, ROW_NUMBER() OVER(PARTITION BY t.id) rn
from t)
Where rn = 1
ROW_NUMBER does not require the ORDER BY clause. Returns the sequential row ordinal (1-based) of each row for each ordered partition. If the ORDER BY clause is unspecified then the result is non-deterministic.
If you have record created date or modified dates you can use those in the ORDER BY clause to alway pick up the latest records.
SQL tables represent unordered sets. There is no first row unless you have a column that specifies the ordering. Let me assume you have such a column.
If you want a particular row, you can use aggregation with an order by:
select array_agg(t order by ? asc limit 1)[ordinal(1)].*
from t
group by id;
? is the column that specifies the ordering.
You can also leave out the order by:
select array_agg(t limit 1)[ordinal(1)].*
from t
group by id;

How to write a query, to produce the desired result?

I want to use a query, showing the top two best Quantity. If the table is like the picture, how can the desired result be produced
You can use DENSE_RANK(). For example:
select
id, name, quantity
from (
select
id, name, quantity,
dense_rank() over(order by quantity desc) as rk
from t
) x
where rk <= 2
DENSE_RANK() computes a number for each row according to an ordering of your choosing. Identical values get the same number, and no numbers are skipped. See SQL Fiddle.
You can use the TOP/LIMIT functions in query. Which would allow you to select a specific number of rows.
using number as 5 you can get the desired result from:
SELECT columnname FROM tablename WHERE condition LIMIT number;
or
SELECT TOP (number)/(percent) columnname FROM tablename WHERE condition;

How to use 'DISTINCT ON' to query last row of duplicate rows?

I came across this tutorial on DISTINCT ON () query. To achieve the output, the following query was used:
SELECT
DISTINCT ON
(bcolor) bcolor, fcolor
FROM
t1
ORDER BY
bcolor,
fcolor;
The
is illustrated here where the top row of the duplicated rows are returned. However, is there a way to return the bottom of the duplicated rows instead? My use case is that multiple applications/registrations might enter and I want to query all the most recent distinct applications.
Appreciate your time, cheers!
I think you just want a descending sort on the second key:
SELECT DISTINCT ON (bcolor) bcolor, fcolor
FROM t1
ORDER BY bcolor, fcolor DESC;
Assuming you have a date or id columns that increments to indicate what the most recent row is, simply order by that column and add DESC to specify ordering by descending order.
SELECT
DISTINCT ON
registration_date, student_id, student_name
FROM
t1
ORDER BY
registration_date desc,
student_id,
student_name;

Rank Over Partition By in Oracle SQL (Oracle 11g)

I have 4 columns in a table
Company Part Number
Manufacturer Part Number
Order Number
Part Receipt Date
Ex.
I just want to return one record based on the maximum Part Receipt Date which would be the first row in the table (The one with Part Receipt date 03/31/2015).
I tried
RANK() OVER (PARTITION BY Company Part Number,Manufacturer Part Number
ORDER BY Part Receipt Date DESC,Order Number DESC) = 1
at the end of the WHERE statement and this did not work.
This would seem to do what you want:
select t.*
from (select t.*
from t
order by partreceiptdate desc
) t
where rownum = 1;
Analytic functions like rank() are available in the SELECT clause, they can't be invoked directly in a WHERE clause. To use rank() the way you want it, you must declare it in a subquery and then use it in the WHERE clause in the outer query. Something like this:
select company_part_number, manufacturer_part_number, order_number, part_receipt_date
from ( select t.*, rank() over (partition by... order by...) as rnk
from your_table t
)
where rnk = 1
Note also that you can't have a column name like company part number (with spaces in it) - at least not unless they are enclosed in double-quotes, which is a very poor practice, best avoided.

SQL Query with MIN function is Returning Multiple Rows

I'm trying to select the estimated hours of a row with the lowest date from a table.
SELECT prev_est_hrs
FROM ( SELECT MIN(change_date), prev_est_hrs
FROM task_history
WHERE task_id = 5
GROUP BY prev_est_hrs
);
However this is returning two rows, why? I thought MIN was supposed to return the lowest only?
Help much appreciated.
You have a GROUP BY clause. The MIN will return the minimum value in each group.
Also, you are only returning the group by value from the outer SELECT.
Mitch is right. One way to get the prev_est_hrs for the record with the earliest change_date, which seems to be what you're trying to find, is with an analytic function:
SELECT prev_est_hrs
FROM (
SELECT prev_est_hrs, ROW_NUMBER() OVER (ORDER BY change_date) AS rn
FROM task_history
WHERE task_id = 5
)
WHERE rn = 1;
You need to consider what should happen if you have two rows with the same date. This would pick one of them at random. If there is some other criteria you could use to break the tie you could add that to the order by clause. If you wanted all matching rows in that case you could use rank() instead; look at dense_rank() as well, they all have their place.
Use this query to do that:
SELECT max(prev_est_hrs) keep (dense_rank first order by change_date)
FROM task_history
WHERE task_id = 5;