SQL Server 2008: How do you SUM based on two conditions? - sql

If I work at a grocery store and need to make orders for inventory, we make orders multiple times a month rather than one large order.
Item
ETA
QTY
Apples
5/6/21
10
Apples
6/12/21
15
Apples
6/30/21
10
Bananas
6/12/21
15
Bananas
7/5/21
20
Cereal
5/15/21
10
Cereal
5/30/21
50
Cereal
7/15/21
20
Is there a way to create a table that sums the QTY, if the item is the same and if the ETA month is the same to know how much of each Item is expected to arrive in a given month?
Ideally, the result I'm looking for is something that looks like this
Item
May
June
July
Apples
10
25
0
Bananas
0
15
20
Cereal
60
0
20
I would need the code to first check to see what month the item is expected to arrive in, and then if there are more than one lines that have the same item and ETA month, SUM the QTY.
I have tried doing CASE WHEN statements but always end up with syntax errors
SELECT
CASE WHEN ETA BETWEEN '2021-05-01' AND '2021-05-31'
AND WHERE Item IN
(SELECT Item
FROM ['Inventory']
GROUP BY Item HAVING COUNT(*)>1)
THEN SUM(QTY)
END AS MAY_QTY
FROM [dbo].['Inventory'];

You just use conditional aggregation:
select item,
sum(case when month(eta) = 5 then qty else 0 end) as may,
sum(case when month(eta) = 6 then qty else 0 end) as jun,
sum(case when month(eta) = 7 then qty else 0 end) as jul
from inventory i
group by item;
I would caution you that using months without a year may lead to problems. That is also true of using unsupported software -- SQL Server 2008 is no longer supported.

First you should group the data by item and month, and then use pivot to convert rows to columns.
select
item,
isnull(may,0) as May,
isnull(june,0) as June,
isnull(july,0) as July
from
(
select item, datename(month, ETA) as _month, sum(qty) as qty
from Inventory
group by item, datename(month, ETA)
) d
pivot
(
sum(qty)
for _month in (may, june, july)
) piv;

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

How to bring corresponding data in the column

How to bring the corresponding data in new columns by comparing there other attributes. here in the below table we have 2 weeks of data along with Store ID and Price type, if the price type is "Regular" then we have to add "Reduced" price with same criteria (Year, Week, StoreID) in the new column and if the price type is "Reduced" then we have to add "Regular" price with same criteria (Year, Week, StoreID) in the new column.
Year
Week
StoreID
PriceType
Price
2021
10
S
Regular
200
2021
10
S
Reduced
150
2021
10
D
Regular
180
2021
10
D
Reduced
120
2021
9
S
Regular
35
2021
9
D
Reduced
40
Has to be change like the below table, in the below output table, "Reduced/Regular" value is 150 in row number 1 because 150 is the corresponding value for 200 with criteria (2021, 10, S) and in 2nd row the Reduced/Regular value is 200 because 200 is the corresponding vale for 150 with criteria (2021, 10, S).
But last 2 rows for week 9 will gives 0 because we don't have corresponding criteria.
Year
Week
StoreID
PriceType
Price
Reduced/Regular
2021
10
S
Regular
200
150
2021
10
S
Reduced
150
200
2021
10
D
Regular
180
120
2021
10
D
Reduced
120
180
2021
9
S
Regular
35
0
2021
9
D
Reduced
40
0
Kindly help with this logic Thanks in advance
You can use window functions and conditional logic:
select t.*,
(case when priceType = 'Regular'
then max(case when priceType = 'Reduced' then price end) over (partition by year, week, storeId)
else max(case when priceType = 'Regular' then price end) over (partition by year, week, storeId)
end) as other_price
from t;
Happily, this is standard SQL and will work in any database.

SQL statement to generate a table of totals by month

I am very unfamiliar with advanced SQL.
Lets say I have the following table (in Access - using Jet 4.0 OLEDBAdapter in VB.NET).
Table - Items
ID Date Account Amount
----- ------ ------- ------
1 1/1/2013 Cash 10.00
2 2/1/2013 Cash 20.00
3 1/2/2013 Cash 30.00
4 2/2/2013 Cash 40.00
5 1/1/2013 Card 50.00
6 2/1/2013 Card 60.00
7 1/2/2013 Card 70.00
8 2/2/2013 Card 80.00
And I want to generate the following - totals for each account per month
Table - Totals
Account Jan Feb
----- ----- ------
Cash 30.00 70.00
Card 110.00 150.00
Is this possible using one SQL statement. I can do it in two but it is very slow.
Edit - the closest I have got is this - but it doesn't generate columns
SELECT accFrom, Sum(amount)
FROM Items
WHERE Year(idate) = '2012'
GROUP BY Month(idate), accFrom
Using your sample data, this is the output I got from the query below with Access 2010.
Account 2013-01 2013-02
------- ------- -------
Card $120.00 $140.00
Cash $40.00 $60.00
My totals don't match your expected output. I suspect your date values were d-m-yyyy format, but my US locale interpreted them as m-d-yyyy. It's better to present dates in yyyy-m-d format to avoid that confusion.
Anyway this query formats the dates as yyyy-mm, and then pivots to generate the columns for each year-month combination. So it will accommodate a growing date range without requiring you to modify the query. And, as the date range grows, you could eventually add a WHERE clause to limit to columns to a convenient subset.
TRANSFORM Sum(i.Amount) AS SumOfAmount
SELECT i.Account
FROM Items AS i
GROUP BY i.Account
PIVOT Format(i.Date,'yyyy-mm');
Since there are exactly 12 months in a year, you do not need to pivot; just calculate the sum for each month:
SELECT Account,
Sum(IIF(Month(Date)=01, Amount, 0)) AS Jan,
Sum(IIF(Month(Date)=02, Amount, 0)) AS Feb,
Sum(IIF(Month(Date)=03, Amount, 0)) AS Mar,
Sum(IIF(Month(Date)=04, Amount, 0)) AS Apr,
Sum(IIF(Month(Date)=05, Amount, 0)) AS May,
Sum(IIF(Month(Date)=06, Amount, 0)) AS Jun,
Sum(IIF(Month(Date)=07, Amount, 0)) AS Jul,
Sum(IIF(Month(Date)=08, Amount, 0)) AS Aug,
Sum(IIF(Month(Date)=09, Amount, 0)) AS Sep,
Sum(IIF(Month(Date)=10, Amount, 0)) AS Oct,
Sum(IIF(Month(Date)=11, Amount, 0)) AS Nov,
Sum(IIF(Month(Date)=12, Amount, 0)) AS "Dec"
FROM Items
WHERE Year(Date) = 2013
GROUP BY Account
Goose is right, you'll need to pivot on your Date column and use SUM() as the aggregate.
The syntax will look something similar to:
SELECT account, [1/1/2013] as jan, [2/1/2013] as feb, ... -- each month you want to select
FROM
(
SELECT date, account, amount FROM items
)
PIVOT
(
SUM(amount) FOR date IN
(
[1/1/2013], [2/1/2013], ... -- each date you want to have its own column
)
) AS pvt

Splitting SQL Data Into Months

I have a Datatable with several hundred rows for this year in it. (MS SqlServer 2k8)
I would like to split this data set out into customer enquiries / Month.
What I have so far is;
Select count(id) As Customers, DatePart(month, enquiryDate) as MonthTotal, productCode From customerEnquiries
where enquiryDate > '2012-01-01 00:00:00'
group by productCode, enquiryDate
But this then produces a row for each data item. (Whereas I want a row per month for each data item.)
So how do I change the above query, so that instead of getting
1 1 10
1 1 10
1 1 11
1 2 10
1 2 10
...
I get
2 1 10 <-- 2 enquiries for product code 10 in month 1
1 1 11 <-- 1 enquiries for product code 11 in month 1
2 2 10 <-- 2 enquiries for product code 10 in month 2
etc
And as a bonus question, is there an easy way of naming each month so the output is Jan, Feb, March instead of 1,2,3 in the month column?
Try this
Select count(id) As Customers, DatePart(month, enquiryDate) as MonthTotal, productCode From customerEnquiries
where enquiryDate > '2012-01-01 00:00:00'
group by productCode, DatePart(month, enquiryDate)
This may help you.
For the Bonus, DATENAME(MONTH, enquiryDate) will give you the name of the Month.