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

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.

Related

increment if not same value of next column in SQL

I am trying to use the Row Number in SQL. However, it's not giving desired output.
Data :
ID Name Output should be
111 A 1
111 B 2
111 C 3
111 C 3
111 A 4
222 A 1
222 A 1
222 B 2
222 C 3
222 B 4
222 B 4
This is a gaps-and-islands problem. As a starter: for the question to just make sense, you need a column that defines the ordering of the rows - I assumed ordering_id. Then, I would recommend lag() to get the "previous" name, and a cumulative sum() that increases everytime the name changes in adjacent rows:
select id, name,
sum(case when name = lag_name then 0 else 1 end) over(partition by id order by ordering_id) as rn
from (
select t.*, lag(name) over(partition by id order by ordering_id) lag_name
from mytable t
) t
SQL Server 2008 makes this much trickier. You can identify the adjacent rows using a difference of rows numbers. Then you can assign the minimum id in each island and use dense_rank():
select t.*,
dense_rank() over (partition by name order by min_ordcol) as output
from (select t.*,
min(<ordcol>) over (partition by name, seqnum - seqnum_2) as min_ordcol
from (select t.*,
row_number() over (partition by name order by <ordcol>) as seqnum,
row_number() over (partition by name, id order by <ordcol>) as seqnum_2
from t
) t
) t;

Counting number of orders depending on city

I have a temp table that is being created, we will say that column 1 is an order_id, and column 2 is user_id, column 3 is start_date, column 4 is end_date and column 5 is city.
order_id user_id Start_date end_date city
101 1 200001 200101 X
101 2 200101 200110 y
101 3 200110 200112 z
101 3 200112 200210 z
I want to count by city the number of order_ids that moved out of it to another city and in another column the number of order_ids that moved into it from another city.
I would like it to come out as a table, like this:
city moved_out_orders moved_into_orders
x 1 0
y 1 1
z 0 1
You can do:
with
x as (
select a.city as from_city, b.city as to_city
from t a
join t b on a.order_id = b.order_id
and a.city <> b.city
and a.end_date = b.start_date
),
o (city, cnt) as (
select from_city, count(*) from x group by from_city
),
i (city, cnt) as (
select to_city, count(*) from x group by to_city
)
select
coalesce(i.city, o.city) as city,
o.cnt as moved_out_orders,
i.cnt as moved_in_orders
from i
full join o on o.city = i.city
Hmmm . . . I think you just want to enumerate the rows for each order and then discard the highest and lowest for each count:
select city,
sum(case when seqnum_desc > 1 then 1 else 0 end) as moved_out,
sum(case when seqnum_asc > 1 then 1 else 0 end) as moved_in
from (select t.*,
row_number() over (partition by orderid order by startdate) as seqnum_asc,
row_number() over (partition by orderid order by startdate desc) as seqnum_desc
from t
) t
group by city;
EDIT:
You appear to have adjacent rows in the same city. Seems strange, but instead you can use lead() and lag():
select city,
sum(case when next_city <> city then 1 else 0 end) as moved_out,
sum(case when prev_city <> city then 1 else 0 end) as moved_in
from (select t.*,
lag(city) over (partition by orderid order by startdate) as prev_city,
lead(city) over (partition by orderid order by startdate) as next_city
from t
) t
group by city;

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

SQL Query to find streak with unique record types

This is my example table data:
CustomerType Date Records
1 2018-01-01 233
2 2018-01-01 12
1 2018-01-02 0
2 2018-01-02 34
1 2018-01-03 0
2 2018-01-03 35
1 2018-01-04 0
2 2018-01-04 0
1 2018-01-05 5562
2 2018-01-05 3
I would like the output to show the maximum 0 Record streak, by CustomerType, to be fetched for each CustomerType. In other words, I would like the maximum number of zero records in a row for each particular CustomerType
Example output
CustomerType MaxZeroRecordsStreak
1 3
2 1
The farthest I've gotten so far is something like this:
SELECT CustomerType,
(SELECT COUNT(*)
FROM Table1 as t1
AND Records = '0'
AND t1.Date <= t2.Date) AS MaxZeroRecordsStreak
FROM Table2 As t2
ORDER BY CustomerType ASC;
But this is clearly not what I want.
Any help with this complex query would be appreciated.
Most databases support the ANSI-standard window functions. You can do this using the difference of row_numbers(). The following gets all sequences of zeros for a customer type:
select customertype, count(*) as num_zeros
from (select t.*,
row_number() over (partition by records, customertype order by date) as seqnum_rt,
row_number() over (partition by customertype order by date) as seqnum_t
from t
) t
where records = 0
group by records, customertype, seqnum_t - seqnum_rt;
You can get the maximum just by using this as a subquery:
select customertype, max(num_zeros)
from (select customertype, count(*) as num_zeros
from (select t.*,
row_number() over (partition by records, customertype order by date) as seqnum_rt,
row_number() over (partition by customertype order by date) as seqnum_t
from t
) t
where records = 0
group by records, customertype, seqnum_t - seqnum_rt
) t
group by customertype;

SQL Rank column based on condition

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