SQL Rank column based on condition - sql

From the table data I should derive the Rank column.
Aim is to select Unique Duns based on below conditions:
Max(ConfidenceCode)
If Confindencde is same, If DeliveryAddressSeq=0 has just one row select that
If Confindencde is same, If DeliveryAddressSeq=0 has many rows then select min of CustomerCode
So, finally I require Rank=1 data as desired output

The rank window function should do the trick:
SELECT Duns, ConfidenceCode, DeliveryAddressSeq, CustomerCode
FROM (SELECT Duns, ConfidenceCode, DeliveryAddressSeq, CustomerCode,
RANK() OVER (PARTITION BY duns
ORDER BY ConfidenceCode ASC,
CASE DeliveryAddressSeq WHEN 0 THEN 0
ELSE 1
END ASC,
CustomerCode DESC) AS rk
FROM mytable)
WHERE rk = 1

Since you wanted to have the rank 1 only, you were looking for customercode 501, 504, 507
SELECT duns,
confidencecode,
deliveryaddressseq,
customercode,
[rank]
FROM (SELECT *,
RANK() OVER (PARTITION BY duns
ORDER BY confidencecode DESC,
deliveryaddressseq,
customercode) AS [rank]
FROM t_duns) tt
WHERE [rank] = 1
Result
duns confidencecode deliveryaddressseq customercode rank
1001 10 1 501 1
1002 10 0 504 1
1003 10 0 507 1

Related

Oracle SQL: How to add a col to assign a seq no. but only 1 and 2 (per unique id)

Is there a way to assign a value ("IdNo") sequentially, 1 and 2, per CustNo? Below is my query (or I can put this query in a view), but not sure how to add an "IdNo" column that will just assign a "1" and "2" respectively, per unique CustNo.
with row as
(select z.*,
row_number ()
over (partition by CustNo
order by FoodDate desc) rn
from table z)
select CustNo,
Food,
FoodDate
from row
where rn <= 2
order by CustNo, FoodDate desc
Below is what I want it to look like with the IdNo added...
IdNo CustNo Food FoodDate
1 101 Red-Apple 7/5/22
2 101 Red-Apple 7/5/22
1 256 Red-Apple 7/11/22
2 256 Red-Cherry 5/20/22
1 418 Blue-Muffin 4/1/22
2 418 Blue-Berry 3/16/22
1 599 Orange-Persimmon 2/8/22
2 599 Red-Apple 1/23/22
1 654 Blue-Berry 12/4/21
2 654 Yellow-Banana 11/27/21
Just add rn on your query.
with row as
(select z.*,
row_number ()
over (partition by CustNo
order by FoodDate desc) rn
from table z)
select rn as IdNo,
CustNo,
Food,
FoodDate
from row
where rn <= 2
order by CustNo, FoodDate desc

redshift: how to find row_number after grouping and aggregating?

Suppose I have a table of customer purchases ("my_table") like this:
--------------------------------------
customerid | date_of_purchase | price
-----------|------------------|-------
1 | 2019-09-20 | 20.23
2 | 2019-09-21 | 1.99
1 | 2019-09-21 | 123.34
...
I'd like to be able to find the nth highest spending customer in this table (say n = 5). So I tried this:
with cte as (
select customerid, sum(price) as total_pay,
row_number() over (partition by customerid order by total_pay desc) as rn
from my_table group by customerid order by total_pay desc)
select * from cte where rn = 5;
But this gives me nonsense results. For some reason rn doesn't seem to be unique (for example there are a bunch of customers with rn = 1). I don't understand why. Isn't rn supposed to be just a row number?
Remove the partition by in the definition of row_number():
with cte as (
select customerid, sum(price) as total_pay,
row_number() over (order by total_pay desc) as rn
from my_table
group by customerid
)
select *
from cte
where rn = 5;
You are already aggregating by customerid, so each customer has only one row. So the value of rn will always be 1.

Get MAX value of each record in group by query

I have a query in SQL looks like that:
select fldCustomer, fldTerminal, COUNT(fldbill)
from tblDataBills
group by fldCustomer, fldTerminal
order by fldCustomer
results looks like:
fldCustomer fldTerminal (number of bills)
0 1 19086
0 2 10
0 5 236
1 1 472
1 5 3
1 500 19
2 1 292
2 500 22
how can i get the MAX count of each customer so i get results like
0 1 19086
1 1 472
2 1 292
Thanks in advance!
Use a subquery with row_number():
select fldCustomer, fldTerminal, cnt
from (select fldCustomer, fldTerminal, COUNT(*) as cnt,
row_number() over (partition by fldCustomer order by count(*) desc) as seqnum
from tblDataBills
group by fldCustomer, fldTerminal
) db
where seqnum = 1
order by fldCustomer ;
Note that in the event of ties, this will arbitrarily return one of the rows. If you want all of them, then use rank() or dense_rank().
This might require a little trickery with the RANK() function
SELECT fldCustomer, fldTerminal, [(number of bills)]
FROM (
SELECT fldCustomer, fldTerminal, COUNT(fldbill) [(number of bills)],
RANK() OVER (PARTITION BY fldCustomer ORDER BY COUNT(fldbill) DESC) Ranking
FROM tblDataBills
GROUP BY fldCustomer, fldTerminal
) a
WHERE Ranking = 1

How to calculate unique rank in SQL Server (without any duplication)?

I want to calculate unique rankings but I get duplicate rankings
Here's my attempt:
SELECT
TG.EMPCODE,
DENSE_RANK() OVER (ORDER BY TS.COUNT_DEL DESC, TG.COUNT_TG DESC) AS YOUR_RANK
FROM
(SELECT
EmpCode,
SUM(CASE WHEN Tgenerate = 1 THEN 1 ELSE 0 END) AS COUNT_TG
FROM
TBLTGENERATE1
GROUP BY
EMPCODE) TG
INNER JOIN
(SELECT
EMP_CODE,
SUM(CASE WHEN STATUS = 'DELIVERED' THEN 1 ELSE 0 END) AS COUNT_DEL
FROM
TBLSTAT
GROUP BY
EMP_CODE) TS ON TG.EMPCODE = TS.EMP_CODE;
The output I get is like this:
EID Rank
---------
102 1
105 2
101 2
103 3
106 4
There is same rank for 105 and 101.
How do I calculate unique ranking?
Use ROW_NUMBER() instead of DENSE_RANK():
SELECT TG.EMPCODE,
ROW_NUMBER() OVER (ORDER BY TS.COUNT_DEL DESC, TG.COUNT_TG DESC) AS YOUR_RANK
Ties will then be given sequential rankings.

How to get the last inserted value for every id in SQL Server 2008?

I have to count the unique status from multiple values. Here is my table example
Id Status OrderId
-------------------
1 1 43
2 2 43
3 1 44
Desired output
It should give the count(status) for Status '1' is 1 and Status '2' is 1. But when using count its giving 2 for status '1'.
You have to do
count(DISTINCT status)
instead of
count(status)
to get
unique status from multiple values.
EDIT:
If you want to get (not count) the Status value of the last inserted record for every OrderId, then you can do:
SELECT Status
FROM (
SELECT Id, Status, OrderId,
ROW_NUMBER() OVER (PARTITION BY OrderId
ORDER BY Id DESC) AS rn
FROM mytable ) t
WHERE t.rn = 1
If you want to get the last status for each order:
with cte as(select *, row_number()
over(partition by OrderID order by Id desc) from TableName)
select * from cte where rn = 1
Or:
select * from (select *, row_number()
over(partition by OrderID order by Id desc) from TableName) t
where rn = 1