Calculate total sales without missing values while joining two tables - mysql

I have a query
I have to calculate monthly sales per branch and customer (Data coming from one table)
Data should look like below
I can write the query for Jan_2019 total sales:
I create a temp table for Feb_2019. I can use the join and combine the 2 tables, but in Feb_2019 if there are new customers added, then when joining the tables I am missing new customers, and due to this the total sales for that month are not matching.
Can any one help?
I have written the query like this below
;with a as
(
select branchid, customer, sum(totalsales) as jan_totalsales from tableA
where year = 2019 and month = 1
group by customer, branched
), feb as
(
select branchid, customer, sum(totalsales) as feb_totalsales from tableA
where year = 2019 and month = 2
group by customer, branched
)
select a.branchid, feb.branchid, a.jan_totalsales, feb.feb_totalsales
from a
left join feb on feb.branchid = a.branchid
I have to create this in a temp table and do it for march_2019
Again, I am not getting new customers as I am joining from Jan data.
Can anyone help me to make this simple?

What you are after here is a conditional aggregate. This should get you on the right path:
SELECT branchid,
customer,
SUM(CASE WHEN [Year] = 2019] AND [Month] = 1 THEN totalsales ELSE 0 END) AS JanSales,
SUM(CASE WHEN [Year] = 2019] AND [Month] = 2 THEN totalsales ELSE 0 END) AS FebSales,
....
FROM YourTable
GROUP BY branchid,
customer;
If you don't undertstand how this works, please do ask. At the end of the day, it's you who has to support the SQL, not myself or other volunteers on Stack Overflow.

Related

Getting the number of users for this year and last year in SQL

My table is like this:
root_tstamp
userId
2022-01-26T00:13:24.725+00:00
d2212
2022-01-26T00:13:24.669+00:00
ad323
2022-01-26T00:13:24.629+00:00
adfae
2022-01-26T00:13:24.573+00:00
adfa3
2022-01-26T00:13:24.552+00:00
adfef
...
...
2021-01-26T00:12:24.725+00:00
d2212
2021-01-26T00:15:24.669+00:00
daddfe
2021-01-26T00:14:24.629+00:00
adfda
2021-01-26T00:12:24.573+00:00
466eff
2021-01-26T00:12:24.552+00:00
adfafe
I want to get the number of users in the current year and in previous year like below using SQL.
Date Users previous_year
2022-01-01 10 5
2022-01-02 20 15
The code is written as follows.
select CAST(root_tstamp as DATE) as Date,
count(DISTINCT userid) as users,
count(Distinct case when CAST(root_tstamp as DATE) = dateadd(MONTH,-12,CAST(root_tstamp as DATE)) then userid end) as previous_year
FROM table1
But it returns 0 for previous_year values.
How can I fix that?
Possible solution for SQL Server:
WITH cte AS ( SELECT 2022 [year]
UNION ALL
SELECT 2021 )
SELECT cte.[year],
COUNT(DISTINCT test.userId) current_users_amount,
COUNT(DISTINCT CASE WHEN YEAR(test.root_tstamp) < cte.[year]
THEN test.userId
END) previous_users_amount
FROM test
JOIN cte ON YEAR(test.root_tstamp) <= cte.[year]
GROUP BY cte.[year]
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=88b78aad9acd965bdbac4c85a0b81927
This query (for MySql) returns unique number of userids where the root_timestamp is in the current year, by day, and the number of unique userids for the same day last year. If there is no record for a day in the current year nothing will be displayed for that day. If there are rows for the current year, but no rows for the same day last year, then NULL will be shown for that lastyear column.
SELECT cast(ty.root_tstamp as date) as Dte,
COUNT(DISTINCT ty.userId) as users_this_day,
count(distinct lysd.userid) as users_sameday_lastyear
FROM test ty
left join
test lysd
on cast(lysd.root_tstamp as date)=date_add(cast(ty.root_tstamp as date), interval -1 year)
WHERE YEAR(ty.root_tstamp) = year(current_date())
GROUP BY Dte
If you wish to show output rows for calendar days even if there are no rows in current year and/or last year, then you also need a calendar table to be introduced (let's hope that it is not what you need)

SQL query to group transactions by month

----------------------------------------
|transaction_id|customer_id|month|value|
----------------------------------------
I am looking for a SQL query that would return customers ID of the customers that had more transactions in the month of October instead of November or of customers that ONLY had transactions in November (and none in October). The month column is of type string (not a date)
I was thinking an inner join could do it, but past that I do not know how to approach this problem.
This is what I attempted
select customer_id
from tbl_name
where (select count(month is 'October') > count(month is 'November') from tbl_name)
Thank you
You count records. So you aggregate. You want counts per customer_id. So you'd group by customer_id. You forgot this in your query.
Then you'd compare the counts in the HAVING clause, i.e. after having counted October and November records.
select customer_id
from tbl_name
where month in ('October', 'November')
group by customer_id
having count(case when month = 'October' then 1 end) >
count(case when month = 'November' then 1 end)
or count(case when month = 'October' then 1 end) = 0;
You don't need to access the table twice as you see. Just aggregate and see what you have :-)

Select count of customers that purchased at least one from two specific categories in the same month

I'm trying to write a query to count the customers that purchased at least one from order_type=0 and one order_type=1 during the same month in 2014
I have two tables.
The order table that have:
order_id
customer_id
aquisition_date
orders_category table:
order_id
order_type (the type of the orders it may have 0, 1, 2, 3, 5, 8 ...etc )
I tried with this query but it didn't work, I know it's not complete and I missed the month condition!
Select count(user_id) From order
join orders_category
on order.order_id = orders_category.order_id
Where (order_type=0 or order_type=1)
and extract (year from order.aquisition_date)=2014
group by user_id
having count (case when type_id=0 then null else null end) > 0
and count (case when type_id=1 then null else null end) > 0;
I don't know how to find users with at least 1 order from order_type=0 & 1 order of order_type=1, in the same month.
You could use this query, based on what you already had. However, I suggest you change the name of the table order to orders as order is a reserved word:
select count(distinct user_id)
from (
select user_id, month(aquisition_date)
from orders
inner join order_category
on orders.order_id = order_category.order_id
where order_type in (0, 1)
and year(aquisition_date) = 2014
group by user_id, month(aquisition_date)
having count(distinct order_type) = 2
) as base
SQL fiddle
I selected the month also in the sub-select, as it will be interesting to look at the output of that query on its own during your analysis.

SQL query: calculate profile or loss in given 2 tables

I have 2 tables storing income:
id name date price isDel
1 abc 2012-01-26 613.90 0
2 cde 2012-01-25 530.10 0
and expenses:
id name price date isDel
1 b1 334.90 2012-01-26 0
2 b1 41.90 2012-01-25 0
3 d1 61.90 2012-01-25 0
I would like to get the result as follows:
date total income total expense profile n loss
2012-01-25 530.10 103.80 426.30
2012-01-26 613.90 344.90 26.90
Thanks. Can anyone provide SQL solutions? I did refer some member's question and answer at stackoverflow but I can't modify to want I need. Please help.
Provided you want profit/loss per day this should do:
SELECT Inc.date, TotalInc, TotalExp, TotalInc - TotalExp AS ProfitNLoss
FROM
(
SELECT date, SUM(price) as TotalInc
FROM Income
WHERE isdel = 0
GROUP BY date) as Inc
LEFT OUTER JOIN
(
SELECT date, SUM(price) as TotalExp
FROM Expense
WHERE isdel = 0
GROUP BY date) as Exp
ON Inc.date = Exp.date
UNION
SELECT Exp.date, TotalInc, TotalExp, TotalInc - TotalExp AS ProfitNLoss
FROM
(
SELECT date, SUM(price) as TotalInc
FROM Income
WHERE isdel = 0
GROUP BY date) as Inc
RIGHT OUTER JOIN
(
SELECT date, SUM(price) as TotalExp
FROM Expense
WHERE isdel = 0
GROUP BY date) as Exp
ON Inc.date = Exp.date
Argh, this is "give me the codes" question, but I'll give you few hints:
mySQL GROUP BY tutorial
mySQL GRUOP BY aggregate functions
mySQL subqueries
So what you need to do:
Create list of all unique dates (unfortunately I haven't find a way to generate list of dates within sql without table query or without long php array, if anyone knows a way to do this I'll be glad to add it to anser), so you will have to do this:
SELECT date FROM income GROUP BY date;
-- If there's a chance that you'll have record in expenses and not in income:
(SELECT date FROM income GROUP BY date)
UNION (SELECT date FROM expenses GROUP BY date;)
GROUP BY date;
-- Or create table containing just list of all dates (best option)
And than join all unique dates with expenses and income:
SELECT SUM(expenses.price) AS expenses, SUM(incomes.price) AS income, dates.date
FROM unique_dates -- or from your subquery
LEFT JOIN incomes ON incomes.date = unique_dates.date
LEFT JOIN expenses ON expenses.date = unique_dates.date
GROUP BY unique_dates.date
Oh and I have no idea what does profile n loss mean.
Thanks to Pheiberg and appreciated for your prof reply.
I just did some little change so it will return 0 when table has no record or return NULL, So that Profit calculation still able to cal even given -ve value. Here the code share to u guys.
note: im using MySQL
SELECT Inc.create_dt, IFNULL(TotalInc,0), IFNULL(TotalExp,0), IFNULL(TotalInc,0) - IFNULL(TotalExp,0) AS ProfitNLoss
FROM
(
SELECT create_dt, SUM(price) as TotalInc
FROM income
WHERE IsDel= 0
GROUP BY create_dt) as Inc
LEFT OUTER JOIN
(
SELECT create_dt, SUM(price) as TotalExp
FROM expenses
WHERE IsDel= 0
GROUP BY create_dt) as Exp
ON Inc.create_dt= Exp.create_dt
UNION
SELECT Exp.create_dt, IFNULL(TotalInc,0), IFNULL(TotalExp,0), IFNULL(TotalInc,0) - IFNULL(TotalExp,0) AS ProfitNLoss
FROM
(
SELECT create_dt, SUM(price) as TotalInc
FROM income
WHERE IsDel= 0
GROUP BY create_dt) as Inc
RIGHT OUTER JOIN
(
SELECT create_dt, SUM(price) as TotalExp
FROM expenses
WHERE IsDel= 0
GROUP BY create_dt) as Exp
ON Inc.create_dt= Exp.create_dt

Selecting data by year, month and week from table

I have the following tables:
Table: promotion_asset
promotion_id
asset_id
(a promotion can have many assets)
Table: promotion_tracking
id(PK)
asset_id
date_scanned
(logging table for every time an asset is scanned )
I want to TRY in one query to be able to identify how many times assets in a specific promotion ID, have been scanned: this year, this month, and this week.
i've tried lots of different methods but cannot find a single query that returns the correct results.
I only have sql server, so I was able to test this for the Year and Month functions, looked up the WeekOfYear for mysql
SELECT pa.promotion_id
, SUM(CASE
WHEN YEAR(pt.date_scanned) = YEAR(GETDATE()) THEN 1
ELSE 0
END CASE) AS ThisYear
, SUM(CASE
WHEN YEAR(pt.date_scanned) = YEAR(GETDATE())
AND MONTH(pt.date_scanned) = MONTH(GETDATE()) THEN 1
ELSE 0
END CASE) AS ThisMonth
, SUM(CASE
WHEN WEEKOFYEAR(pt.date_scanned) = WEEKOFYEAR(GETDATE()) THEN 1
ELSE 0
END CASE) AS ThisWeek
FROM promotion_tracking AS pt
INNER JOIN promotion_asset AS pa ON pt.asset_id = pa.asset_id
GROUP BY pa.promotion_id