SUM from a preview query (mysql) - mysql

I have this query from Uploads table:
select
Costumer as Customer,
max(Week) as 'Max Week',
count(distinct(POS)) as 'Total POS'
from Uploads
where year = 2022
group by Costumer;
and returns this:
Customer
Max Week
Total POS
Customer A
3
65
Customer B
5
27
Customer C
3
33
This table has an additional column named Inventory and I want to know the SUM(Inventory) but with the weeks filtered before.
For example:
Customer
Max Week
Total POS
Inventory
Customer A
3
65
456
Customer B
5
27
123
Customer C
3
33
2345

You can solve this issue by using Row_Number like this
SELECT t.[Total POS],
t.customer,
t.week MaxWeek,
t.SumInventoryPerWeek SumForMaxWeek
FROM (
select
Costumer as Customer,
Week as week,
count(distinct(POS)) as 'Total POS',
SUM(Inventory) SumInventoryPerWeek,
ROW_NUMBER() OVER(PARTITION BY Costumer ORDER BY Week DESC) rw
from Uploads
where year = 2022
group by Costumer,Week
) t
WHERE t.rw=1

Related

Aggregate information from one table to another with a different “layout” (mysql)

this is my starting table which provides sales information by Id.
Id
Store_Name
Market
Sales
Main_Product
1
StoreA
Rome
10
a
2
StoreB
Rome
15
b
3
StoreC
Rome
9
c
4
Mag1
Paris
10
a
5
Mag2
Paris
23
b
6
Mag3
Paris
12
c
7
Shop1
London
11
a
8
Shop2
London
31
b
9
Shop3
London
45
c
10
Shop4
London
63
d
In order to build a report and create some dynamic sentences, I will need the dataset to be "paginated" as per below table:
Id
Dimension
Dimension_Name
Sales
Main_Product
1
ShoppingCentre
StoreA
10
a
1
Market
Rome
34
a
2
ShoppingCentre
StoreB
15
b
2
Maket
Rome
34
b
3
ShoppingCentre
StoreC
9
c
3
Market
Rome
34
c
Do you have any tip about how to build the last table starting from the first one?
To sum-up:
The new table will be always by Id
Aggregation of market sales happens at row level where every single shopping centre is located
This is the query that I have built so far but wondering if there is a better and more efficient way to accomplish the same:
with store_temp_table as (
select
id
,Store_Name
,Market
, Main_Product
, sum(Sales) as Sales
from Production_Table
where 1=1
group by
1,2,3,4
)
, market_temp_table as (
select
market
, sum(Sales) as Sales
from Production_Table
where 1=1
group by
1
)
, store_temp_table_refined as(
Select
a.id
,a.Main_Product
, 'ShoppingCentre' as Dimension_Name
,SUM(a.Sales) as Sales
FROM store_temp_table a INNER JOIN
market_temp_table b on a.market = b.market
group by
1,2,3
)
, market_temp_table_refined as (
Select
a.id
,a.Main_Product
, 'Market' as DimensionName
,SUM(b.Sales) as Sales
FROM store_temp_table a INNER JOIN
market_temp_table b on a.market = b.market
group by
1,2,3
)
select * from store_temp_table_refined
union all
select * from market_temp_table_refined
Thank you
Use a CTE that returns the dimensions that you want and cross join it to a query that returns the columns of the table and an additional column with the total sales of each market:
WITH Dimensions(id, Dimension) AS (VALUES
ROW(1, 'ShoppingCentre'),
ROW(2, 'Market')
)
SELECT p.Id,
d.Dimension,
CASE d.id WHEN 1 THEN p.Store_Name ELSE p.Market END Dimension_Name,
CASE d.id WHEN 1 THEN p.Sales ELSE p.MarketSales END Sales,
p.Main_Product
FROM Dimensions d
CROSS JOIN (SELECT *, SUM(Sales) OVER (PARTITION BY Market) AS MarketSales FROM Production_Table) p
ORDER BY p.id, d.id;
Or, with UNION ALL:
SELECT Id,
'ShoppingCentre' Dimension,
Store_Name Dimension_Name,
Sales,
Main_Product
FROM Production_Table
UNION ALL
SELECT Id,
'Market',
Market,
SUM(Sales) OVER (PARTITION BY Market),
Main_Product
FROM Production_Table
ORDER BY Id,
CASE Dimension WHEN 'ShoppingCentre' THEN 1 WHEN 'Market' THEN 2 END;
See the demo.

Mysql Query sum and group by not showing a row with null values

I have this query:
SELECT Customer, SUM(SoldUnits) AS SoldUnits
FROM Uploads
WHERE Year = 2021
AND Week = 11
GROUP BY Customer;
And Returns me:
Customer
SoldUnits
CUSTOMER A
55
CUSTOMER B
32
CUSTOMER D
17
CUSTOMER C exist, but it doesn't have data for the week 11 and I want to show CUSTOMER C with 0 SoldUnits. How Can I do that?
Assuming your table does have all customers you want to appear in the report, you could do a conditional summation and remove the WHERE clause:
SELECT Customer,
SUM(CASE WHEN Year = 2021 AND Week = 11
THEN SoldUnits ELSE 0 END) AS SoldUnits
FROM Uploads
GROUP BY Customer;

Month on month retention in a year in SQL

How can we calculate the month on month cumulative retention rate in SQL
Bill_Date Customer_id
2021-01-01 1
2021-01-23 2
2021-01-29 3
2021-02-17 1
2021-02-19 2
2021-03-01 3
Retention Rate= (Total Number of unique Customers in present Month)/(Total Number of Customers in previous Months)
Expected Output
January : 100%
February : 66.7%
March : 25%
February =(Unique customers in feb)/((Unique customers in jan)
March=(Unique customers in march)/((Unique customers in jan)+(Unique
customers in feb)
Consider a window function for cumulative sum of unique customer per year/month:
WITH sub AS (
SELECT YEAR(c.Bill_Date) AS bill_year,
MONTH(c.Bill_Date) AS bill_month,
COUNT(DISTINCT c.customer_id) AS unq_customers
FROM customer_bills c
GROUP BY YEAR(c.Bill_Date),
MONTH(c.Bill_Date)
)
SELECT bill_year,
bill_month,
unq_customers,
IFNULL(
unq_customers /
(SUM(unq_customers) OVER(ORDER BY bill_month) -
unq_customers),
1
) * 100 AS retention_rate
FROM sub
Online Demo

How to display the days when there are no records in MariaDB?

I have the following table called employees:
employee
name
101
John
102
Alexandra
103
Ruth
And the table called records:
employee
assistance
101
2022-02-01
101
2022-02-02
101
2022-02-07
Let's suppose that I want to display the employee number, name and the days of the month in which there were absences between 2022-02-01 and 2022-02-07 (taking into account that days 05 and 06 are weekends). In that case, the result would be the following:
employee
name
absence
101
John
4,5
How do I get that result?
So far I have developed a query where the days of the month in which there are attendances are displayed. Said query is as follows:
SELECT e.employee,
e.name,
r.assistance AS assistance,
OF employees and
JOIN LEFT(SELECT employee, GROUP_CONCAT(DIFFERENT EXTRACT(DAY SINCE assistance)
ORDER BY STATEMENT(DAY FROM assistance)) AS assistance FROM records
WHERE assistance BETWEEN '2022-02-01' AND '2022-02-07' GROUP BY employee) r ON e.employee = employee
WHERE (r.no_employee IS NOT NULL) ORDER BY name ASC
I would like to know how to implement the days in which there were absences and not consider the weekends. I've done several tests but I'm still stuck. I'm working with MariaDB 10.4.11
You use a recursive common table expression (requires mariadb 10.2+ or mysql 8) to get the list of dates in the date range, and join against that:
with recursive date_range as (
select '2021-12-01' dt
union all
select dt + interval 1 day from date_range where dt < '2021-12-07'
)
select employee.employee, group_concat(day(date_range.dt) order by date_range.dt) faults
from date_range
cross join employee
left join records on records.employee=employee.employee and records.assistance=date_range.dt
where weekday(date_range.dt) < 5 and records.employee is null
group by employee.employee
fiddle
If you are just looking for one employee, add that as a where condition.

How to get count of employees with total employee with group by year

This is my employee table
empid name Date_of_joining
1 dilip 2010-01-30
2 suresh 2001-03-01
3 ramesh 2003-01-01
I want to get the number of employees with total employees group by employee date of joining
expected output
year new joining total employees
2001 10 10
2002 12 22
2003 15 27
query
select YEAR(`DATE_OF_JOINING`) as 'year', COUNT(*) as 'count1',sum(count(*)) from employee
GROUP BY YEAR(`DATE_OF_JOINING`)
You need a running total using a user defined variable.
You need a derived table cause running totals don't work with group by statement
SET #SUM = 0;
SELECT
YEAR,
NoOfEmployee AS newJoining,
(#SUM := #SUM + NoOfEmployee) AS totalJoining
FROM (
SELECT
YEAR(Date_of_joining) AS YEAR,
COUNT(*) AS NoOfEmployee
FROM
employees
GROUP BY
YEAR(Date_of_joining)
) O
here a sample