SQL Query - Group and SUM of Values - sql

I have the following database structure:
ID | Payment (Decimal) | PaymentDate (DateTime) | PaymentStatus(int)
I am currently able to get a grouping of all of the payments over time by Year and Date and get the total across all Payment Status's using the following query;
Select
YEAR = YEAR(DueDate),
MONTH = MONTH(DueDate),
MMM = UPPER(left(DATENAME(MONTH,DueDate),3)),
Totals = sum(Payment)
from
PaymentSchedules
Where DueDate IS NOT NULL
Group by
YEAR(DueDate),
MONTH(DueDate),
DATENAME(Month,DueDate)
Order By
YEAR,
MONTH
This gives me the results so far so good.
What I would like to be able to do is have added totals for the splits in each section. So for example if each payment could be Paid (1) or Unpaid (2) or Overdue (3) I would like to not only get the number of paid / unpaid / overdue but I would also like to get the total value of unpaid items / paid items / Overdue items for each Year / Month combination.

You just need to add SUMs with CASE statements inside to only sum payments when the correct status is detected, like this:
Select YEAR = YEAR(DueDate),
MONTH = MONTH(DueDate),
MMM = UPPER(left(DATENAME(MONTH,DueDate),3)),
TotalPaid = sum(case when PaymentStatus = 1 then Payment else 0 end),
TotalUnpaid = sum(case when PaymentStatus = 2 then Payment else 0 end),
TotalOverdue = sum(case when PaymentStatus = 3 then Payment else 0 end),
Totals = sum(Payment)
from PaymentSchedules
Where DueDate IS NOT NULL
Group by YEAR(DueDate),
MONTH(DueDate),
DATENAME(Month,DueDate)
Order By YEAR,
MONTH

Since there are only 3 categories, I would suggest use CASE statement directly.
Select
YEAR = YEAR(DueDate),
MONTH = MONTH(DueDate),
MMM = UPPER(left(DATENAME(MONTH,DueDate),3)),
Paid_sum = sum(CASE When PaymentStatus = 1 THEN Payment ELSE 0 END),
Unpaid_sum = sum(CASE When PaymentStatus = 2 THEN Payment ELSE 0 END),
Overdue_sum = sum(CASE When PaymentStatus = 3 THEN Payment ELSE 0 END),
Totals = sum(Payment)
from
PaymentSchedules
Where DueDate IS NOT NULL
Group by
YEAR(DueDate),
MONTH(DueDate),
DATENAME(Month,DueDate)
Order By
YEAR,
MONTH

Related

How do I get transactions amount > 1000 of all months in SQL

I have been trying to pull customers who have transaction amount greater than 1000 in all months. This is what I have tried so far. But it doesn't look like it's working when I do individual customer test.
Select customer
,extract(month from trans_date) as mth
,extract(year from trans_date) as yr
,sum(trans_amount) as amt
, case when mth in (8) and amt > 1000 then 1 else 0 end as aug
, case when mth in (9) and amt > 1000 then 1 else 0 end as sep
, case when mth in (10) and amt > 1000 then 1 else 0 end as oct
, case when mth in (11) and amt > 1000 then 1 else 0 end as nov
, case when mth in (12) and amt > 1000 then 1 else 0 end as de_c
from transaction
group by 1,2,3
having (aug = 1 and sep = 1 and oct=1 and nov=1 and de_c = 1)
Select customer
,extract(month from trans_date) as mth
,extract(year from trans_date) as yr
,sum(trans_amount) as amt
from transaction
-- filter only those months you want to check, e.g.
where trans_date between date '2021-08-01' and date '2021-12-31'
group by 1,2,3
-- check that every month there was an individual transaction over 1000
qualify
min(max(trans_amount))
over (partition by customer) > 1000
Edit:
Same logic to get just the customer without detail rows:
select customer
from
(
Select customer, max(trans_amount) as maxamt
from transaction
-- filter only those months you want to check, e.g.
where trans_date between date '2021-08-01' and date '2021-12-31'
group by
customer
,trunc(trans_date, 'mon') -- for every month
) as dt
group by customer
-- check that every month there was an individual transaction over 1000
having min(maxamt) > 1000
You may want to try using Over (partition by) something like this.
Select customer
,extract(month from trans_date) as mth
,extract(year from trans_date) as yr
,sum(trans_amount) over (partition by customer , extract(month from trans_date)) as
total
From transaction
Order by total desc
Assuming your data is one record per customer per month.
To get unique customers where trans_amt > 1000 in every month :
select customer
from transaction
group by customer
having count(1) = count(case when trans_amt > 1000 then 1 else 0 end)
To get all records only for customers where trans_amt > 1000 in every month :
select customer, trans_date, trans_amt
from transaction
qualify count(1) over (partition by customer) = count(case when trans_amt > 1000 then 1 else 0 end) over (partition by customer)

SQL How to group data into separate month columns

So I'm running this query to get the name of the customer, total amount ordered, and number of orders they've submitted. With this query, I get their entire history from March to July, what I want is the name, march amount total/# of orders, april amount total/# of orders, may amount total/# of orders, ..... etc.
SELECT customer_name,MONTH(created_on), SUM(amount), COUNT(order_id)
FROM customer_orders
WHERE created_on BETWEEN '2020-03-01' AND '2020-08-01'
GROUP BY customer_name, MONTH(created_on)
If you want the values in separate columns, then use conditional aggregation:
SELECT customer_name,
SUM(CASE WHEN MONTH(created_on) = 3 THEN amount END) as march_amount,
SUM(CASE WHEN MONTH(created_on) = 3 THEN 1 ELSE 0 END) as march_count,
SUM(CASE WHEN MONTH(created_on) = 4 THEN amount END) as april_amount,
SUM(CASE WHEN MONTH(created_on) = 4 THEN 1 ELSE 0 END) as april_count,
. . .
FROM customer_orders
WHERE created_on >= '2020-03-01' AND
created_on < '2020-08-01'
GROUP BY customer_name;
Notice that I changed the date filter so it does not include 2020-08-01.

Month number retention cohort calculation issue with Redshift

I'm trying to calculate user retention cohorts in redshift by month for the last 9 months. But I'm running into an issue where the month cohorts in the below query aren't being rolled into the correct month.
The data types I'm querying are:
userid - varchar
activated-varchar
Here is the query I'm trying to run:
with by_month as
(SELECT
userid
DATE_TRUNC('month', cast ("activated" as date)) AS joined_month
FROM customers
GROUP BY 1, 2),
first_month as
(select userid,
joined_month,
FIRST_VALUE(order_month) OVER (PARTITION BY userid ORDER BY
joined_month asc rows unbounded preceding) AS first
FROM by_month),
months as (select userid,
joined_month,
first,
extract(month from (joined_month - first_month)) as month_number
from first_month)
SELECT
first as "cohort",
SUM(CASE WHEN month_number = '0' THEN 1 ELSE 0 END) AS " Month 0",
SUM(CASE WHEN month_number = '1' THEN 1 ELSE 0 END) AS " Month 1",
SUM(CASE WHEN month_number = '2' THEN 1 ELSE 0 END) AS " Month 2",
SUM(CASE WHEN month_number = '3' THEN 1 ELSE 0 END) AS " Month 3",
SUM(CASE WHEN month_number = '4' THEN 1 ELSE 0 END) AS " Month 4",
SUM(CASE WHEN month_number = '5' THEN 1 ELSE 0 END) AS " Month 5",
SUM(CASE WHEN month_number = '6' THEN 1 ELSE 0 END) AS " Month 6",
SUM(CASE WHEN month_number = '7' THEN 1 ELSE 0 END) AS " Month 7",
SUM(CASE WHEN month_number = '8' THEN 1 ELSE 0 END) AS " Month 8",
SUM(CASE WHEN month_number = '9' THEN 1 ELSE 0 END) AS " Month 9"
from months
where first_month >= '2018-08-01'
GROUP BY 1
ORDER BY 1 desc
When I get the results back, I get an impossible number for a couple of cohorts:
Such as:
Cohort Month 0 Month 1
'2019-01-01' 95 120
I did some digging and found the month numbers aren't being counted correctly For instance, for the cohort of '2019-01-01 the month_ number is t's capturing 0,1, and 3 correctly but 2 is being miss-attributed to month 1. Any help on the fix would be much appreciated thank you!
Now, try
SELECT userid, joined_month, first_month, month_number FROM months
WHERE first = '2019-01-01'
(feel free to add other columns to drill down to the problem) add activated, order_month, etc until you get the right handle on what is causing it.

Monthly sales as column

SQL question, making monthly and yearly sales as column:
I have two tables:
t_items (item_num, item_name, itm_qnt)
t_items_dtl (item_num, invdate, itm_qnt_out, itm_qnt_in)
Columns are:
itm_qnt = current stock
invdate = invoice date
item_qnt_out = number of sold specific item in the invoice
item_qnt_in = number of returned specific item in the invoice
I want to get the following columns:
item_num | item_name | currnt_stock | QTY sold 2018 | QTY sold:Jan2018 | Feb 2018 | March 2018 .... Dec 2018
For now I used this query but it gives me only the total sales of each item:
SELECT
i.item_num AS ItemNum,
i.item_name AS ItemName,
sum(d.itm_qnt_out-d.itm_qnt_in) AS QTOUT,
i.itm_qnt AS Stock
FROM
dbo.t_items AS i
FULL OUTER JOIN
t_items_dtl AS d ON i.item_num = d.item_num
GROUP BY
i.item_num, i.item_name, i.itm_qnt;
How can I add monthly and yearly sales by column (not rows)?
Depending on the database you are using there may be more elegant ways to get year and month from a date but bottom-line, you probably want something like:
SELECT
i.item_num AS ItemNum,
i.item_name AS ItemName,
sum(d.itm_qnt_out-d.itm_qnt_in) AS QTOUT,
sum(CASE WHEN to_char(invdate,'mm') = '01' THEN d.itm_qnt_out-d.itm_qnt_in ELSE 0 END) AS QTOUTJan,
sum(CASE WHEN to_char(invdate,'mm') = '02' THEN d.itm_qnt_out-d.itm_qnt_in ELSE 0 END) AS QTOUTFeb,
sum(CASE WHEN to_char(invdate,'mm') = '03' THEN d.itm_qnt_out-d.itm_qnt_in ELSE 0 END) AS QTOUTMar,
/*Repeat for every month*/
i.itm_qnt AS Stock
FROM
dbo.t_items AS i
FULL OUTER JOIN
t_items_dtl AS d ON i.item_num = d.item_num
WHERE to_char(invdate, 'yyyy') = '2018'
GROUP BY
i.item_num, i.item_name, i.itm_qnt;
Compared to your code, I have defined a column for each month + added a WHERE to filter the entire thing to 2018.

infuse a sum of the value in the another column with a different filter than the total count column

First here's a sample table.
enter image description here
Provider_name patient date status length
AF AGUIR00001 07/05/2018 3 30
AF ABBOT00001 07/05/2018 30
BB ADAMS00001 07/05/2018 3 30
BB ACEVE00001 07/06/2018 3 30
I have created a query that lets me count the total number of appointments versus the number of appointments with a certain status(eg checked out). I was able to create it and group it by provider.
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout
from appointment
group by provider_name
Then I moved on to the next phase which was to get the total length of those appointments with checkedout status. I made this query but it does not break down into each provider.
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
(select sum(length) from appointment where status = 3
and date between '06/01/2018' and '07/06/2018')
from appointment where date between '06/01/2018' and '07/06/2018'
group by provider_name
I need it so that the last column in the query is segregated per provider_name.
Thank you in advance for helping me out.
Actually, you were on the right way, try this:
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum(case when status = 3 then length else 0 end) as len_status3
from appointment
where date between '2018-01-06' and '2018-06-07'
group by provider_name;
According to your last comment, you need a WITH ROLLUP modifier for GROUP BY as in the following :
select coalesce(provider_name,'Total') as provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum(case when status = 3 then length else 0 end) as len_status3
from appointment
where date between '2018-01-06' and '2018-06-07'
group by provider_name with rollup;
SQL Fiddle Demo
you shoul do as for checkedoutout
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum( case when status = 3 then length else 0 ) as total_length
from appointment where date between '06/01/2018' and '07/06/2018'
group by provider_name