SQL Server SELECT Query to show sum - sql

It ll be great if you guys help me with this
product_no prod_name qty DOA
---------------------------------------------------------------
1 2BL 4 12/12/14
2 CCN 6 14/12/14
3 MNN 7 16/12/14
3 MNN 5 17/12/14
2 CCN 6 02/01/15
3 MNN 7 06/01/15
I need output in single select query if i select DOA between 1/12/14 to 30/12/14
It should show sum (qty) as opening, prod_name and rest of qty and product i.e(02/01/15 to 06/01/15) in another column as purchase (DOA not in 1/12/14 to 30/12/14). Thanks in advance

Assuming, of course, the point rightly raised by Joel in his comment about date formats is taken care of, by you:
Select product_no, prod_name,
Sum(Case When DOA >= '01/12/2014' And DOA <= '30/12/2014' Then Qty Else 0 End) as openingQty,
Sum(Case When DOA < '01/12/2014' Or DOA > '30/12/2014' Then Qty Else 0 End) as purchaseQty
From Table_Name_Here Group By
product_no, prod_name

Related

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

SQL Troubleshooting Help on Table Structure

I'm attempting to calculate average number of days between a customer's 1st and 3rd purchase, but struggling to get the data ordered in a way that will allow me to calculate.
I currently have the below data table. (Note: Order sequence number refers to the number order for that customer.)
Order Date
Customer Number
Order Sequence Number
2020-09-20
1
1
2021-01-20
1
2
2021-01-21
1
3
2020-10-01
2
1
2020-08-06
3
1
2020-09-06
3
2
2020-09-09
3
3
I've been trying to get the data to look like the following table. [To then be able to calculate datediff on the last two columns.]
Customer Number
Order Count
First Order Date
Third Order Date
1
3
2020-09-20
2021-01-21
2
1
2020-10-01
Null
3
3
2020-08-06
2020-09-09
I've completely messed up the code, but here's what I've been trying.
CREATE TABLE X2 as
SELECT
customer_number,
max(order_sequence_number) as order_count,
CASE
WHEN order_sequence_number = 1 then order_date
ELSE null
END as first_order_date,
CASE
WHEN order_sequence_number = 3 then order_date
ELSE null
END as third_order_date
FROM X1
GROUP BY customer_number;
Can someone please tell me what I'm missing? Thanks in advance!
You are on the right track but you need aggregation functions:
SELECT customer_number,
max(order_sequence_number) as order_count,
MAX(CASE WHEN order_sequence_number = 1 THEN order_date END) as first_order_date,
MAX(CASE WHEN order_sequence_number = 3 THEN order_date END) as third_order_date
FROM X1
GROUP BY customer_number;
To get the difference in days, you would just subtract the two expressions using whatever date arithmetic is supported in your database.

SQL Query two values for each record

I'm trying to query a customers table to get the total number of accounts per rep grouped by whether they were created this year or before.
CUSTOMER NAME
ACCOUNT REP
DATE CREATED
The query I'm trying to return would look like.
REP | NEW_ACCOUNTS | OLD_ACCOUNTS | TOTAL
-----------------------------------------
Tom | 100 | 12 | 112
Ted | 15 | 1 | 16
The query I've written looks as follows.
SELECT REP, CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END AS ThisYear
FROM CUSTOMERS
GROUP BY REP, DATE_CREATED
Unfortunately, this is giving me
REP | ThisYear
-----------------------------------------
Tom | 1
Ted | 0
Tom | 0
Ted | 1
Ted | 1
I think you want conditional aggregation:
SELECT REP,
SUM(CASE WHEN YEAR(GETDATE()) = YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS NEW_ACCOUNTS,
SUM(CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS OLD_ACCOUNTS,
COUNT(*) as TOTAL
FROM CUSTOMERS
GROUP BY REP;
This assumes that creation dates are not in the future -- a reasonable assumption.
If you want one row per REP, then the only column in the GROUP BY should be REP.
You can want conditional aggregation :
SELECT REP,
SUM(CASE WHEN YEAR(GETDATE()) = YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS NEW_ACCOUNTS,
SUM(CASE WHEN YEAR(GETDATE()) > YEAR(DATE_CREATED) THEN 1 ELSE 0 END) AS OLD_ACCOUNTS, COUNT(*) AS TOTAL
FROM CUSTOMERS
GROUP BY REP;

Sql Cleanse to one row

I am struggling with the solution to a query and any help would be greatly appreciated, I end up tying myself In knots with temptables and I'm sure there must be an easier way.
I have a database currently producing the below results - this is as it comes with no joins or production prior.
Acc No | prod No | Product Type | product Cost
12345678 1 Red Toy £100
12345678 2 Blue Toy £150
12345678 3 White Toy £300
12398654 1 White Toy £300
12398765 1 Red Toy £100
I only want one row per account number but don't want to lose the information. I would also like some sums. The below should hopefully show what I mean though there would be more columns:
Acc No | Prod total | cost | Prod1type | Prod1cost |prod2typ
12345678 3 £550 Red Toy £100 BlueToy
12398654 1 £300 White Toy £300 Null
I hope this explains it. I'm aware I would end up with many more columns but it would make my life so much easier.
Any help would be hugely appreciated,
Thanks in advance,
With out considering adding ProdType you could use this query.
Assume also there is only 1 product per line in table.
select acc_no, count(*) as prod_total, sum(cost) as total_cost
from table
group by acc_no
order by acc_no asc
to get all ProdType for a coresponding acc_no you could use
select distinct prodtype
from table
where acc_no='exact_number'
You can use multiple case statements to get your expected output.
Create sample data:
select 12345678 as Accno , 1 as prodno, 'Red Toy' as Producttype , 100 as Cost into #temp union all
select 12345678 as Accno , 2 as prodno, 'Blue Toy' as Producttype , 150 as Cost union all
select 12345678 as Accno , 3 as prodno, 'White Toy' as Producttype , 300 as Cost union all
select 12398654 as Accno , 1 as prodno, 'White Toy' as Producttype , 300 as Cost union all
select 12398765 as Accno , 1 as prodno, 'Red Toy' as Producttype , 100 as Cost
Query:
select accno, count(distinct prodno) Prodtotal, sum(cost) totalCost, max(case when prodno = 1 then Producttype end ) Product1type,
sum (case when prodno = 1 then cost end) Product1cost, max(case when prodno = 2 then Producttype end ) Product2type,
sum (case when prodno = 2 then cost end) Product2cost,max(case when prodno = 3 then Producttype end ) Product3type,
sum (case when prodno = 3 then cost end) Product3cost from #temp
group by accno
Output:
Formatting might be little bit different, but I assume this is your expected output.
accno Prodtotal totalCost Product1type Product1cost Product2type Product2cost Product3type Product3cost
12345678 3 550 Red Toy 100 Blue Toy 150 White Toy 300
12398654 1 300 White Toy 300 NULL NULL NULL NULL
12398765 1 100 Red Toy 100 NULL NULL NULL NULL

SQL Query to get sums among multiple payments which are greater than or less than 10k

I am trying to write a query to get sums of payments from accounts for a month. I have been able to get it for the most part but I have hit a road block. My challenge is that I need a count of the amount of payments that are either < 10000 or => 10000. The business rules are that a single payment may not exceed 10000 but there can be multiple payments made that can total more than 10000. As a simple mock database it might look like
ID | AccountNo | Payment
1 | 1 | 5000
2 | 1 | 6000
3 | 2 | 5000
4 | 3 | 9000
5 | 3 | 5000
So the results I would expect would be something like
NumberOfPaymentsBelow10K | NumberOfPayments10K+
1 | 2
I would like to avoid doing a function or stored procedure and would prefer a sub query.
Any help with this query would be greatly appreciated!
I suggest avoiding sub-queries as much as possible because it hits the performance, specially if you have a huge amount of data, so, you can use something like Common Table Expression instead. You can do the same by using:
;WITH CTE
AS
(
SELECT AccountNo, SUM(Payment) AS TotalPayment
FROM Payments
GROUP BY AccountNo
)
SELECT
SUM(CASE WHEN TotalPayment < 10000 THEN 1 ELSE 0 END) AS 'NumberOfPaymentsBelow10K',
SUM(CASE WHEN TotalPayment >= 10000 THEN 1 ELSE 0 END) AS 'NumberOfPayments10K+'
FROM CTE
You can get the totals per account using SUM and GROUP BY...
SELECT AccountNo, SUM(Payment) AS TotPay
FROM payments
GROUP BY AccountNo
You can use that result to count the number over 10000
SELECT COUNT(*)
FROM (
SELECT AccountNo, SUM(Payment) AS TotPay
FROM payments
GROUP BY AccountNo
)
WHERE TotPay>10000
You can get the the number over and the number under in a single query if you want but that's a but more complicated:
SELECT
COUNT(CASE WHEN TotPay<=10000 THEN 1 END) AS Below10K,
COUNT(CASE WHEN TotPay> 10000 THEN 1 END) AS Above10K
FROM (
SELECT AccountNo, SUM(Payment) AS TotPay
FROM payments
GROUP BY AccountNo
)