SQL group into ranges the sum of values - sql

I have an table which contains inventory information for some items.
AGENT_ID
ITEM_ID
WAREHOUSE_ID
QTY
BATCH
AGE
100
IT101
1
10
B001
5
100
IT101
2
13
B002
8
100
IT101
1
15
B003
18
100
IT102
3
10
B005
42
The age column indicates how long the items had been in the warehouse. I need to generate an output which contains how the items had aged in the warehouse. These need to be summed into ranges based on the age. Below is an example output.
AGENT_ID
ITEM_ID
WAREHOUSE
R1(1-10)
R2(11-20)
R3(21<)
100
IT101
1
10
15
0
100
IT101
2
13
0
0
100
IT102
3
0
0
10
The first row in the second table represents that 10 items of IT101 had been in warehouse 1 for a period of (1-10) days, 15 items been in warehouse 1 for (11-20) days and so on.
Is there a way to group from agent, item, warehouse ids and sum the item quantity at the same time grouping it into ranges?
The first table may contain several millions of records. Tried this with some inner queries but it takes so much time.

you need to use conditional aggregation:
select AGENT_ID, ITEM_ID, WAREHOUSE
, sum(case when age between 1 and 10 then QTY end) "R1(1-10)"
, sum(case when age between 11 and 20 then QTY end) "R2(11-20)"
, sum(case when age > 20 then QTY end) "R3(21<)"
From table
group by AGENT_ID, ITEM_ID, WAREHOUSE

Related

SQL Create Column Headers by Month ID

I am trying to extract itemised sales data for the past 12 months and build a dynamic table with column headers for each month ID. Extracting the data as below works, however when I get to the point of creating a SUM column for each month ID, I get stuck. I have tried to find similar questions but I'm not sure of the best approach.
Select Item, Qty, format(Transaction Date,'MMM-yy')
from Transactions
Data Extract:
Item
Qty
Month ID
A123
50
Apr-22
A123
30
May-22
A123
50
Jun-22
A321
50
Apr-22
A999
25
May-22
A321
10
Jun-22
Desired Output:
Item
Apr-22
May-22
Jun-22
A123
50
30
50
A321
50
Null
10
A999
Null
25
Null
Any advice would be greatly appreciated.
This is a typical case of pivot operation, where you
first filter every value according to your "Month_ID" value
then aggregate on common "Item"
WITH cte AS (
SELECT Item, Qty, FORMAT(Transaction Date,'MMM-yy') AS Month_ID
FROM Transactions
)
SELECT Item,
MAX(CASE WHEN Month_ID = 'Apr-22' THEN Qty END) AS [Apr-22],
MAX(CASE WHEN Month_ID = 'May-22' THEN Qty END) AS [May-22],
MAX(CASE WHEN Month_ID = 'Jun-22' THEN Qty END) AS [Jun-22]
FROM cte
GROUP BY Item
Note: you don't need the SUM as long as there's only one value for each couple <"Item", "Month-Year">.

rolling sum to calculate YTD for each month group by product and save to separate columns using SQL

I have a data like this:
Order_No Product Month Qty
3001 r33 1 8
3002 r34 1 11
3003 r33 1 17
3004 r33 2 3
3005 r34 2 11
3006 r34 3 1
3007 r33 3 -10
3008 r33 3 18
I'd like to calculate total YTD qty for product and each month and save to separate columns. Below is what I want
Product Qty_sum_jan Qty_sum_feb Qty_sum_mar
r33 25 28 36
r34 11 22 23
I know how to use window function to calculate rolling sums but I have no idea to group them to separate columns. I currently use something like this:
case when Month = 1 then sum(Qty) over(partition by Product order by Month) else 0 end as Qty_sum_jan,
case when Month <=2 then sum(Qty) over(partition by Product order by Month) else 0 end as Qty_sum_feb,
case when Month <=3 then sum(Qty) over(partition by Product order by Month) else 0 end as Qty_sum_mar,
This will get me rolling sum by order but how to get to product level like what I show above? If I use group by then it will throw an error since Month is not in group by clause. I also cannot just use max to get the last value since qty can be negative so the last value may not be maximum. I use sparkSQL by the way
To my understanding, there is no need to use window functions. The following query achieves your desired output:
select
product,
sum(case when month = 1 then qty else 0 end) as sum_qty_jan,
sum(case when month <= 2 then qty else 0 end) as sum_qty_feb,
sum(case when month <= 3 then qty else 0 end) as sum_qty_mar
from your_table
group by 1;
Output:
product
sum_qty_jan
sum_qty_feb
sum_qty_mar
r33
25
28
36
r34
11
22
23

Get multiple counts by 5 year increments

This is my table:
index_melanoma_yr Total_Melanoma Total_Virus
2000 700 12
2001 746 7
2002 724 12
2003 815 15
2004 893 16
2005 1020 22
I would like to count by 5 year increments. So, 2000-2004, 2005-2009, etc. I can hard code this, but since there are so many years, I'm wondering if there is a more efficient way.
Here's how I got the initial counts:
SELECT index_melanoma_yr,
COUNT(DISTINCT PersonID) AS Total_Melanoma,
SUM( CASE
WHEN index_virus_yr IS NOT NULL THEN
1
ELSE
0
END
) AS Total_Virus
FROM Asare_ViralMelanoma_IndexDates
GROUP BY index_melanoma_yr
ORDER BY index_melanoma_yr
you can perform some simple maths year / 5 * 5 on the year column, and then GROUP BY that. Assuming that the year column is integer
SELECT MIN(index_melanoma_yr) AS Year_Start,
MAX(index_melanoma_yr) AS Year_End,
COUNT(DISTINCT PersonID) AS Total_Melanoma,
SUM( CASE
WHEN index_virus_yr IS NOT NULL THEN
1
ELSE
0
END
) AS Total_Virus
FROM Asare_ViralMelanoma_IndexDates
GROUP BY index_melanoma_yr / 5 * 5
ORDER BY Year_Start

SQL - Case when product exists, fill up its corresponding value to all rows within the partition

I have the something like the following monthly data set.
I have a Product, company ID, Date, and Quantity. A company (denoted by Company ID) can buy multiple products. I want to create a new column that will have the quantity of Product 'C' if the company bought in the month at each line item. If Product 'C' is not bought, then return 0.
Product Company_ID Date Quantity Desired_Calculated_Column
A 1 5/1/2019 100 300
B 1 5/1/2019 200 300
C 1 5/1/2019 300 300
A 2 6/1/2019 150 125
B 2 6/1/2019 250 125
C 2 6/1/2019 125 125
A 3 7/1/2019 175 0
B 3 7/1/2019 275 0
I have been trying to partition the data based on Product and Company ID. I have been trying to leverage the LAST_VALUE but haven't been successful.
LAST_VALUE(quantity) OVER (PARTITION BY Date, Company_ID
ORDER BY product_group
) AS Desired_Calculated_Column
You don't want last_value(). You can use conditional aggregation, assuming that 'C' occurs once per group:
MAX(CASE WHEN product_group = 'C' THEN quantity ELSE 0 END) OVER
(PARTITION BY Date, Company_ID) AS C_quantity

SQL: How to group rows with the condition that sum of fields is limited to a certain value?

This is my table:
id user_id date balance
1 1 2016-05-10 10
2 1 2016-05-10 30
3 2 2017-04-24 5
4 2 2017-04-27 10
5 3 2017-11-10 40
I want to group the rows by user_id and sum the balance, but so that the sum is equal or less than 30. Moreover, I need to display the minimum date in the group. It should look like this:
id balance date_start
1-1 10 2016-05-10
1-2 30 2016-05-10
2-1 15 2017-04-24
Excuse for my language. Thanks.
You should be able to do so by using group by & having, here is an example of what may solve your case :
SELECT id, user_id, SUM(balance) as balance, data_start
FROM your_table
GROUP BY user_id
HAVING SUM(balance) >= 30
AND MIN(date_start)
This is a good way to do it with one query, but it is a complex query and you should be careful if using it on a very large tables.