Getting rank from count of last months orders - sql

I received following task:
Write a query returning all ORDER_IDs the time of the order, the rank of the merchant by order count for the previous month, and the merchant's primary sales channel for the previous month.
The Table has following cells:
ORDER_ID
MERCHANT_ID
ORDER_TIMESTAMP
SALES_CHANNEL_TYPE_ID
01
1
01/09/2021
3
02
2
03/09/2021
5

Related

How do I count the number of days in a snapshot table per Id under a specific status but start the count differently based on another Id column?

The Data:
I have a table, BaseTable that is a daily snapshot table. It has four columns, SnapshotDate, RequestId, EmployeeId, and Status. It is a table of each Request Id and their status every day (either active or inactive) and which employee is assigned to it. The Employee assigned can and does change over time.
What I am trying to accomplish:
I am trying to write a query that will calculate the number of days a Request was inactive, however, the tricky part is that it should not start counting until after an EmployeeId has been assigned to the request and therefore it should count differently for each Employee. For example, if Employee 1 and 2 were each assigned to Request Id 908, Employee 1 was assigned on Jan 1st 2022 and Employee 2 took over on Feb 1st 2022 then Employee 2 will have a smaller number showing for the number of days the request was inactive (a month less since he started a month later). The output of the query if it was run on 2022-05-01 (May 1st) would look like the following:
RequestId
EmployeeId
EmployeeAssignedDate
DaysInactive
908
1
2022-01-01
120
908
2
2022-02-01
89
732
4
2022-03-01
61
732
1
2022-04-01
30
732
3
2022-05-01
0
What I've done so far:
Using the BaseTable I created a table EmployeeDates that shows the distinct RequestId, EmployeeId, and EmployeeAssignedDate:
EmployeeDates AS (
SELECT
RequestId,
EmployeeId,
Min(SnapshotDate) AS EmployeeAssignedDate,
FROM
BaseTable
GROUP BY 1, 2
)
The next thing I tried was the query below but it did not correctly start counting after each assigned date, the output was that it showed the number of days inactive per RequestId and completely ignored the EmplyeeAssignedDates. Meaning in the above example instead of showing 120 days, and 89 days in 1st and 2nd rows respectively, it showed 120 days for both and in rows 3,4,and 5 it showed 61 days.
SELECT
ed.RequestId,
ed.EmployeeId,
ed.EmployeeAssignedDate,
SUM(IF(bt.Status = 'inactive'
AND bt.SourcingRequestSnapshotDate >= ed.EmployeeAssignedDate, 1, 0))
AS DaysInactive
FROM
EmployeeDates ed
LEFT JOIN
BaseTable bt
ON
ed.RequestId = bt.RequestId
GROUP BY
1, 2, 3
If anyone knows a method of how to calculate what I'm looking for I would really appreciate the help.

Count total without duplicate records

I have a table that contains the following columns: TrackingStatus, Year, Month, Order, Notes
I need to calculate the total number of tracking status for each year and month.
For example, if the table contains the following orders:
TrackingStatus
Year
Month
Order
Notes
F
2020
1
33
F
2020
1
33
DFF
E
2020
2
36
xxx
A
2021
3
34
X1
A
2021
3
34
DD
A
2021
3
88
A
2021
2
45
The result should be:
• Tracking F , year 2020, month 1 the total will be one (because it's the same year, month, and order).
• Tracking A , year 2021, month 2 the total will be one. (because there is only one record with the same year, month, and order).
• Tracking A , year 2021, month 3 the total will be two. (because there are two orders within the same year and month).
So the expected SELECT output will be like that:
TrackingStatus
Year
Month
Total
F
2020
1
1
E
2020
2
1
A
2021
2
1
A
2021
3
2
I was trying to use group by but then it will count the number of records which in my scenario is wrong.
How can I get the total orders for each month without counting “duplicate” records?
Thank you
You can use a COUNT DISTINCT aggregation function, whereas the COUNT allows you to count the values, but the DISTINCT condition will allow each value only once.
SELECT TrackingStatus,
Year,
Month,
COUNT(DISTINCT Order) AS Total
FROM tab
GROUP BY TrackingStatus,
Year,
Month
ORDER BY Year,
Month
Here you can find a tested solution in a MySQL environment, though this should work with many DBMS.

Monthly average without aggregating on monthly level

The table below is aggregating order_value
using data from the last 6 month, without creating an additional subquery I would like to calculate the monthly average of all orders over the last 6 month (see desired output table below).
Table
customer_id | order_timestamp | order_value
A 2020-01-01 10:30:51 100
Desired output table
customer_id | sum_orders | monthly_avg_orders
A 100.000 16.666
This is what I already have
select
customer_id,
sum(order_value)
from table
group by customer_id

How to get row count based on other column groups

I need to count the number of dates with which the invoices are made to certain customers in each month
Consider the table named Table1
Branch Month Date Amount
----------------------------------------
B1 April 01/04/20 10000
B1 April 14/04/20 13000
B1 May 01/05/20 25000
B1 May 14/05/20 23000
I tried the folllowing code
Select
Branch, Month, Date, Amount,
Row_Number() over (partition by Branch order by Month) as rowcount
from table1
and the result was
Branch Month Date Amount rowcount
----------------------------------------
B1 April 01/04/20 10000 1
B1 April 14/04/20 13000 2
B1 May 01/05/20 25000 3
B1 May 14/05/20 23000 4
The result I need should count the column named branch based on column month, the desired result is
Branch Month Date Amount rowcount
---------------------------------------------
B1 April 01/04/20 10000 1
B1 April 14/04/20 13000 2
B1 May 01/05/20 25000 1
B1 May 14/05/20 23000 2
Here rowcount is based on both column branch and Month, how can I get this result?
You need to partition by month. Something like this:
row_number() over (partition by Branch, month order by Month)
Note that month is repeated. An order by is needed in SQL Server, so you need something. Other options are:
row_number() over (partition by Branch, month order by (select null))
row_number() over (partition by Branch, month order by date)
I suspect the last is what you really want.

How to count no of days per user on a rolling basis in Oracle SQL?

Following on from a previous question, in which i have a table called orders with information regarding the time an order was placed and who made that order.
order_timestamp user_id
-------------------- ---------
1-JUN-20 02.56.12 123
3-JUN-20 12.01.01 533
23-JUN-20 08.42.18 123
12-JUN-20 02.53.59 238
19-JUN-20 02.33.72 34
I would like to calculate a daily rolling count of the number of days a user made an order in a past 10 days.
For example, in the last 10 days from the 20th June, user 34 made an order on 5 of those days. Then in the last 10 days from the 21st June, user 34 made an order on 6 of those days
In the end the table should be like this:
date user_id no_of_days
----------- --------- ------------
20-JUN-20 34 5
20-JUN-20 123 10
20-JUN-20 533 2
20-JUN-20 238 3
21-JUN-20 34 6
21-JUN-20 123 10
How would the query be written for this kind of analysis?
Please let me know if my question is unclear/more infor is required.
Thanks to you in advancement.
You can use window functions for this. Start by getting one row per user per day. And then use a rolling sum:
select day, user_id,
count(*) over (partition by user_id range between interval '10' day preceding and current row)
from (select distinct trunc(order_timestamp) as day, user_id
from t
) t
Assuming that a user places one order a day maximum, you can use window functions as follows:
select
t.*,
count(*) over(partition by user_id order by trunc(order_timestamp) range 10 preceding) no_of_days
from mytable t
Otherwise, you can get the distinct orders per day first:
select
order_day,
user_id,
count(*) over(partition by user_id order by order_day range 10 preceding) no_of_days
from (select distinct trunc(order_timestamp) order_day, user_id from mytable) t