Trouble with rank and or dense rank - sql

+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
| customer_id | row_num_booking | row_num_service | row_num_perservice | dense_rank | created_at | service_type | id |
+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
| 1244180 | 1 | 4 | 1 | 1 | 2020-11-23T13:28:02.163 | moving | 2778630 |
| 1244180 | 2 | 3 | 1 | 1 | 2020-11-24T10:48:51.994 | appclean | 2781335 |
| 1244180 | 3 | 1 | 1 | 1 | 2020-11-24T14:50:17.648 | homeclean | 2782760 |
| 1244180 | 4 | 1 | 2 | 2 | 2020-12-07T14:15:33.849 | homeclean | 2822332 |
+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
but I expexted to be like this:
+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
| customer_id | row_num_booking | row_num_service | row_num_perservice | dense_rank | created_at | service_type | id |
+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
| 1244180 | 1 | 4 | 1 | 1 | 2020-11-23T13:28:02.163 | mv | 2778630 |
| 1244180 | 2 | 3 | 1 | 2 | 2020-11-24T10:48:51.994 | ac | 2781335 |
| 1244180 | 3 | 1 | 1 | 3 | 2020-11-24T14:50:17.648 | hc | 2782760 |
| 1244180 | 4 | 1 | 2 | 3 | 2020-12-07T14:15:33.849 | hc | 2822332 |
+-------------+-----------------+-----------------+--------------------+------------+-------------------------+--------------+---------+
Do you know how should i change in my code?
row_number() OVER (partition by b.customer_id,b.service_type order by b.service_type) dense_rank

Remove b.service_type from your partition by clause.

Related

How to insert or update a column using SQL based on sorted number of items for each item group

I have two tables 'Product' and 'product_Desc'
+-----------+-------------+
| ProductID | ProductName |
+-----------+-------------+
| 1 | A |
| 2 | B |
+-----------+-------------+
+----+-----------+-------------+-----------+
| Id | ProductID | ProductDec | SortOrder |
+----+-----------+-------------+-----------+
| 1 | 1 | Aero-pink | |
| 2 | 1 | Aero-white | |
| 3 | 1 | Aero-green | |
| 4 | 1 | Aero-Orange | |
| 5 | 2 | Baloon-1 | |
| 6 | 2 | Baloon-2 | |
| 7 | 2 | Baloon-3 | |
+----+-----------+-------------+-----------+
Now, what is the Sql code that can update 'sortOrder' column sequentially for each group of ProductID as shown below:
+----+-----------+-------------+-----------+
| Id | ProductID | ProductDec | SortOrder |
+----+-----------+-------------+-----------+
| 1 | 1 | Aero-pink | 1 |
| 2 | 1 | Aero-white | 2 |
| 3 | 1 | Aero-green | 3 |
| 4 | 1 | Aero-Orange | 4 |
| 5 | 2 | Baloon-1 | 1 |
| 6 | 2 | Baloon-2 | 2 |
| 7 | 2 | Baloon-3 | 3 |
+----+-----------+-------------+-----------+
Please note that these are sample tables, actual tables have thousands of records.
Would appreciate your help on this. Thank you
with cte
as
(
select SortOrder, row_number() over(partition by ProductID order by Id) as newPerProductOrder
from product_Desc
)
update cte
set SortOrder = newPerProductOrder
where (SortOrder <> newPerProductOrder or SortOrder is null)

A Column to count number of distinct values in column X based on column Y?

In SSMS 2016, I have a select statement with various joins which gives me the following data:
| box_barcode | order_number | order_shipment_id | item | qty |
|-------------|--------------|-------------------|----------|-----|
| 3330000001 | 0000105 | FP001 | tshirt-S | 1 |
| 3330000001 | 0000105 | FP001 | tshirt-M | 2 |
| 3330000001 | 0000105 | FP001 | tshirt-L | 2 |
| 3330000005 | 0000108 | FP002 | shorts-S | 2 |
| 3330000005 | 0000108 | FP002 | shorts-M | 1 |
| 3330000005 | 0000120 | FP002 | shorts-S | 1 |
| 3330000010 | 0000120 | FP003 | shirts-M | 2 |
| 3330000010 | 0000120 | FP003 | shirts-L | 2 |
| 3330000010 | 0000121 | FP003 | shirts-S | 3 |
| 3330000010 | 0000121 | FP003 | shirts-M | 3 |
| 3330000010 | 0000122 | FP003 | shirts-S | 2 |
I'd like to add a column to count the number of distinct order_numbers for each box_barcode, for the desired result:
| box_barcode | order_number | order_shipment_id | item | qty | count |
|-------------|--------------|-------------------|----------|-----|-------|
| 3330000001 | 0000105 | FP001 | tshirt-S | 1 | 1
| 3330000001 | 0000105 | FP001 | tshirt-M | 2 | 1
| 3330000001 | 0000105 | FP001 | tshirt-L | 2 | 1
| 3330000005 | 0000108 | FP002 | shorts-S | 2 | 2
| 3330000005 | 0000108 | FP002 | shorts-M | 1 | 2
| 3330000005 | 0000120 | FP002 | shorts-S | 1 | 2
| 3330000010 | 0000120 | FP003 | shirts-M | 2 | 3
| 3330000010 | 0000120 | FP003 | shirts-L | 2 | 3
| 3330000010 | 0000121 | FP003 | shirts-S | 3 | 3
| 3330000010 | 0000121 | FP003 | shirts-M | 3 | 3
| 3330000010 | 0000122 | FP003 | shirts-S | 2 | 3
I'm struggling to find out how best to achieve this. I know of count(distinct..), but would I have to put my current query into a subquery for the count to go against the results of that query first?
One more option with dense_rank and max.
select t.*,
max(rnk) over(partition by box_barcode) as distinct_count
from (select t.*,
dense_rank() over(partition by box_barcode order by order_numbers) as rnk
from t
) t
The highest ranked row (using dense_rank) will be the distinct number of order numbers per box_barcode.
Alas, SQL Server doesn't support count(distinct) as a window function. But it is easy enough to emulate:
select t.*,
sum(case when seqnum = 1 then 1 else 0 end) over (partition by box_barcode) as distinct_count
from (select t.*,
row_number() over (partition by box_barcode, order_numbers order by box_barcode) as seqnum
from t
) t;

SQL How count subset with condition

I have the following table:
+--------+------------+----------------+
| saleId | saleDate | contractId |
+--------+------------+----------------+
| 1 | 01.07.2016 | 1001 |
| 2 | 02.07.2016 | 1001 |
| 3 | 03.07.2016 | 1002 |
| 4 | 04.07.2016 | 1002 |
| 5 | 05.07.2016 | 1001 |
| 6 | 06.07.2016 | 1001 |
+--------+------------+----------------+
I want to count number of previuos sales by contract for each sale (each row)
+--------+------------+------------+------------------------+
| saleId | saleDate | contractId | SalesCountPerContract |
+--------+------------+------------+------------------------+
| 1 | 01.07.2016 | 1001 | 0 |
| 2 | 02.07.2016 | 1001 | 1 |
| 3 | 03.07.2016 | 1002 | 0 |
| 4 | 04.07.2016 | 1002 | 1 |
| 5 | 05.07.2016 | 1001 | 2 |
| 6 | 06.07.2016 | 1001 | 3 |
+--------+------------+------------+------------------------+
select t.*
,row_number() over
(partition by contractId order by saleDate) - 1 as SalesCountPerContract
from mytable t

Considering values from one table as column header in another

I have a base table where I need to calculate the difference between two dates based on the type of the entry.
tblA
+----------+------------+---------------+--------------+
| TypeCode | Log_Date | Complete_Date | Pending_Date |
+----------+------------+---------------+--------------+
| 1 | 18/04/2016 | 19/04/2016 | |
| 2 | 10/04/2016 | 18/04/2016 | 15/04/2016 |
| 3 | 12/04/2016 | 19/04/2016 | |
| 4 | 15/04/2016 | 17/04/2016 | 16/04/2016 |
| 5 | 16/04/2016 | 21/04/2016 | |
| 1 | 19/04/2016 | 20/04/2016 | |
| 2 | 20/03/2016 | 31/03/2015 | |
| 3 | 25/03/2016 | 28/03/2016 | |
| 4 | 26/03/2016 | 27/03/2016 | |
| 5 | 27/03/2016 | 30/03/2016 | |
+----------+------------+---------------+--------------+
I have another look up table which has the column names to be considered based on the TypeCode.
tblB
+----------+----------+---------------+
| TypeCode | DateCol1 | DateCol2 |
+----------+----------+---------------+
| 1 | Log_Date | Complete_Date |
| 2 | Log_Date | Pending_Date |
| 3 | Log_Date | Complete_Date |
| 4 | Log_Date | Pending_Date |
| 5 | Log_Date | Complete_Date |
+----------+----------+---------------+
I am doing a simple DATEDIFF between two dates for my calculation. However I want to lookup which columns to consider for this calculation from tblB and apply it on tblA based on the TypeCode.
Resulting table:
For example: When the TypeCode is 2 or 4 then the calculation should be DATEDIFF(d, Log_Date, Pending_Date), otherwise DATEDIFF(d, Log_Date, Complete_Date)
+----------+------------+---------------+--------------+----------+
| TypeCode | Log_Date | Complete_Date | Pending_Date | Cal_Days |
+----------+------------+---------------+--------------+----------+
| 1 | 18/04/2016 | 19/04/2016 | | 1 |
| 2 | 10/04/2016 | 18/04/2016 | 15/04/2016 | 5 |
| 3 | 12/04/2016 | 19/04/2016 | | 7 |
| 4 | 15/04/2016 | 17/04/2016 | 16/04/2016 | 1 |
| 5 | 16/04/2016 | 21/04/2016 | | 5 |
| 1 | 19/04/2016 | 20/04/2016 | | 1 |
| 2 | 20/03/2016 | 31/03/2015 | | |
| 3 | 25/03/2016 | 28/03/2016 | | 3 |
| 4 | 26/03/2016 | 27/03/2016 | | |
| 5 | 27/03/2016 | 30/03/2016 | | 3 |
+----------+------------+---------------+--------------+----------+
Any help would be appreciated. Thanks.
Use JOIN with CASE expression:
SELECT
a.*,
Cal_Days =
DATEDIFF(
DAY,
CASE
WHEN b.DateCol1 = 'Log_Date' THEN a.Log_Date
WHEN b.DateCol1 = 'Complete_Date' THEN a.Complete_Date
ELSE a.Pending_Date
END,
CASE
WHEN b.DateCol2 = 'Log_Date' THEN a.Log_Date
WHEN b.DateCol2 = 'Complete_Date' THEN a.Complete_Date
ELSE a.Pending_Date
END
)
FROM TblA a
INNER JOIN TblB b
ON b.TypeCode = a.TypeCode

how to write a query to get multilevel data

I have four tables as below:
tblAccount
Id i sprimary key
+----+-----------------+
| Id | AccName |
+----+-----------------+
| 1 | AccountA |
| 2 | AccountB |
+----+-----------------+
tblLocation
Id is primary key.
+----+---------------+
| Id | LocName |
+----+---------------+
| 1 | LocationA |
| 2 | LocationB |
| 3 | LocationC |
+----+---------------+
tblAccountwiseLocation
Id i sprimary key.LocId and AccId are foreign key.
+----+---------------+---------------+
| Id | LocId | AccId |
+----+---------------+---------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 1 | 2 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
+----+---------------+---------------+
tblRSCMaster
Id i sprimary key.LocId and AccId are foreign key.
+----+---------------+---------------+----------------+------------------+
| Id | LocId | AccId | RSCNo | DateOfAddition |
+----+---------------+---------------+----------------+------------------+
| 1 | 1 | 1 | Acc1_Loc1_1_14 | 15/01/2014 |
| 2 | 2 | 1 | Acc1_Loc2_1_14 | 15/01/2014 |
| 3 | 3 | 1 | Acc1_Loc2_1_14 | 15/01/2014 |
| 4 | 1 | 2 | Acc2_Loc1_1_14 | 15/01/2014 |
| 5 | 2 | 2 | Acc2_Loc2_1_14 | 15/01/2014 |
| 6 | 3 | 2 | Acc2_Loc3_1_14 | 15/01/2014 |
| 7 | 1 | 1 | Acc1_Loc1_2_14 | 15/02/2014 |
| 8 | 2 | 1 | Acc1_Loc2_2_14 | 15/02/2014 |
| 9 | 3 | 1 | Acc1_Loc3_2_14 | 15/02/2014 |
| 10 | 1 | 2 | Acc2_Loc1_2_14 | 15/02/2014 |
| 11 | 2 | 2 | Acc2_Loc2_2_14 | 15/02/2014 |
| 12 | 3 | 2 | Acc2_Loc3_2_14 | 15/02/2014 |
| 13 | 1 | 1 | Acc1_Loc1_3_14 | 15/03/2014 |
| 14 | 2 | 1 | Acc1_Loc2_3_14 | 15/03/2014 |
| 15 | 3 | 1 | Acc1_Loc3_3_14 | 15/03/2014 |
| 16 | 1 | 2 | Acc2_Loc1_3_14 | 15/03/2014 |
| 17 | 2 | 2 | Acc2_Loc2_3_14 | 15/03/2014 |
| 18 | 3 | 2 | Acc2_Loc3_3_14 | 15/03/2014 |
| 19 | 1 | 1 | Acc1_Loc1_4_14 | 15/04/2014 |
| 20 | 2 | 1 | Acc1_Loc2_4_14 | 15/04/2014 |
| 21 | 3 | 1 | Acc1_Loc3_4_14 | 15/04/2014 |
| 22 | 1 | 2 | Acc2_Loc1_4_14 | 15/04/2014 |
| 23 | 2 | 2 | Acc2_Loc2_4_14 | 15/04/2014 |
| 24 | 3 | 2 | Acc2_Loc3_4_14 | 15/04/2014 |
| 25 | 1 | 1 | Acc1_Loc1_5_14 | 15/05/2014 |
| 26 | 2 | 1 | Acc1_Loc2_5_14 | 15/05/2014 |
| 27 | 3 | 1 | Acc1_Loc3_5_14 | 15/05/2014 |
| 28 | 1 | 2 | Acc2_Loc1_5_14 | 15/05/2014 |
| 29 | 2 | 2 | Acc2_Loc2_5_14 | 15/05/2014 |
| 30 | 3 | 2 | Acc2_Loc3_5_14 | 15/05/2014 |
+----+---------------+---------------+----------------+------------------+
Acc1_Loc1_1_14 resembles RSC for LocationA of AccountA for Jan 2014.
I need to get a output as below from tblRSCMaster.
+---------------+---------------+----------------+------------------+
| LocId | AccId | RSCNo | DateOfAddition |
+---------------+---------------+----------------+------------------+
| 1 | 1 | Acc1_Loc1_3_14 | 15/03/2014 |
| 1 | 1 | Acc1_Loc1_4_14 | 15/04/2014 |
| 1 | 1 | Acc1_Loc1_5_14 | 15/05/2014 |
| 2 | 1 | Acc1_Loc2_3_14 | 15/03/2014 |
| 2 | 1 | Acc1_Loc2_4_14 | 15/04/2014 |
| 2 | 1 | Acc1_Loc2_5_14 | 15/05/2014 |
| 3 | 1 | Acc1_Loc3_3_14 | 15/03/2014 |
| 3 | 1 | Acc1_Loc3_4_14 | 15/04/2014 |
| 3 | 1 | Acc1_Loc3_5_14 | 15/05/2014 |
+---------------+---------------+----------------+------------------+
Each account has multiple locations and each location has multiple RSCs.
I need to get last three RSCs for each location for AccountA.
I have tried the below query:
SELECT tblAccountwiseLocation.LocId,tblAccountwiseLocation.AccId,tblRSCMaster.RSCNo,tblRSCMaster.DateOfAddition FROM tblAccountwiseLocation
INNER JOIN tblRSCMaster ON tblAccountwiseLocation.LocId= tblRSCMaster.LocId
where tblRSCMaster.AccId=1
But not getting the proper output.
Please help me out.
Thank you all in advance.
You can wrap the existing query inside a common table expression, and use ROW_NUMBER() to get only the last 3 (by tblRSCMaster.DateOfAddition) entries per tblAccountwiseLocation.LocId.
WITH cte AS (
SELECT tblAccountwiseLocation.LocId,
tblAccountwiseLocation.AccId,
tblRSCMaster.RSCNo,
tblRSCMaster.DateOfAddition,
ROW_NUMBER() OVER (PARTITION BY tblAccountwiseLocation.LocId
ORDER BY tblRSCMaster.DateOfAddition DESC) rn
FROM tblAccountwiseLocation
INNER JOIN tblRSCMaster
ON tblAccountwiseLocation.LocId = tblRSCMaster.LocId
AND tblAccountwiseLocation.AccId = tblRSCMaster.AccId
WHERE tblRSCMaster.AccId=1
)
SELECT LocId, AccId, RSCNo, DateOfAddition
FROM cte
WHERE rn <= 3
ORDER BY LocId, AccId, DateOfAddition
An SQLfiddle to test with.
Is this what you need?
select m.*
from (select m.*, row_number() over (partition by accID
order by DateOfAddition desc) as seqnum
from tblRSCMaster
where m.locid = 1
) m
where seqnum <= 3
order by AccId, DateOfAddition;
I think you need to filter on the locid rather than on the AccId to get what you want.