agregate sales totals per years per customer in one transaction - mysql

i have a normal turnover table with 3 columns "customer" , "year", "amount"
(for example)
customer
year
amount
anton
2020
$5
paul
2019
$12
anton
2021
$5
paul
2019
$10
felicia
2021
$5
anton
2019
$12
felipe
2019
$12
and i have the following mysql query
SELECT `customer` , SUM(`amount`) as summ FROM `customer`.`accountsales` WHERE `amount`> 0 GROUP BY `customer` ORDER BY summ DESC ;
This transaction gives me a nice Paretto table with the sales of each customer in descending order
name
sales all years
customer1
sum of all transactions of customer1
customer2
sum of all transactions of customer2
customer3
sum of all transactions of customer3
so far so good, i want to go one step further and i want to create the following table
Name
Sales all years
Sales 2021
Sales2020
Sales2019
customer1
sum1
sum2021 from customer1
sum2020 from customer1
sum2019 from customer1
customer2
sum2
sum2021 from customer2
sum2020 from customer2
sum2019 from customer2
customer3
sum3
sum2021 from customer3
sum2020 from customer3
sum2019 from customer3
but i want to do it in only one transaction, because the initial table is very huge.
can someone give a hint ?
p.S. feel free to edit the title since I am not very inspired today

You can try to use condition aggregate function
Query 1:
SELECT `customer` ,
SUM(`amount`) 'Sales all years',
SUM(CASE WHEN year = 2021 THEN `amount` ELSE 0 END) Sales2021,
SUM(CASE WHEN year = 2020 THEN `amount` ELSE 0 END) Sales2020,
SUM(CASE WHEN year = 2019 THEN `amount` ELSE 0 END) Sales2019
FROM accountsales
GROUP BY `customer`
Results:
| customer | Sales all years | Sales2021 | Sales2020 | Sales2019 |
|----------|-----------------|-----------|-----------|-----------|
| anton | 22 | 5 | 5 | 12 |
| felicia | 5 | 5 | 0 | 0 |
| felipe | 12 | 0 | 0 | 12 |
| paul | 22 | 0 | 0 | 22 |

Related

How to write an SQL query to calculate the average for three consecutive values?

I have a table like this
userID time NoOfVisits
1 2014 50
2 2015 60
3 2016 70
4 2017 80
5 2018 90
6 2019 100
I need to write a sql query which will print time and average of past 3 years NoOfVisits for a particular site.
output should be as
userID time NoOfVisits
1 2014 50.0000
2 2015 55.0000
3 2016 60.0000
4 2017 70.0000
5 2018 80.0000
6 2019 90.0000
Explanation :
For user Id 6 (80+90+100)/3=90.0000
Please help me to solve this problem.
You can use a cumulative average, available in MySQL 8+:
select t.*,
avg(visits) over (order by time rows between 2 preceding and current row) as avg_visits_3
from t;
Assuming there are no gaps between the years (like your sample data), you can self join the table and group by userid, time to get the average:
select
t.userid, t.time, avg(tt.noofvisits) NoOfVisits
from tablename t inner join tablename tt
on tt.time between t.time - 2 and t.time
group by t.userid, t.time
See the demo.
Results:
| userid | time | NoOfVisits |
| ------ | ---- | ---------- |
| 1 | 2014 | 50 |
| 2 | 2015 | 55 |
| 3 | 2016 | 60 |
| 4 | 2017 | 70 |
| 5 | 2018 | 80 |
| 6 | 2019 | 90 |

SQL query calculate and display sum data per each month of the year

I have 'orders' table with some data like the following:
---------------------------------
id | amount | order_date
---------------------------------
1 | 100.00 | 2018-03-12
2 | 120.00 | 2018-03-25
3 | 200.00 | 2018-04-10
4 | 250.00 | 2018-04-20
5 | 300.00 | 2018-05-02
i want to display the SUM('amount') per each month in the current year, i want to use this data to create a chart later.
I want to achieve like this results.
---------------------------------
month | sum(amount)
---------------------------------
January | 0.00
February | 0.00
March | 320.00
April | 450.00
Mai | 300.00
June | 0.00
July | 0.00
August | 0.00
September | 0.00
October | 0.00
November | 0.00
December | 0.00
I create a separate table 'months' containing all the months of the year then i left join 'orders' with it but it didn't work, this is the query i use.
Please help.
SELECT months.month, IFNULL( sum(orders.amount), 0 ) AS amount
FROM months
LEFT OUTER JOIN orders ON month(orders.order_date) = months.month
GROUP BY months.month
update
Finally i made it work this is my query
SELECT IFNULL( sum(orders.amount), 0 ) AS amount
FROM months
LEFT OUTER JOIN orders ON monthName(orders.order_date) = months.month
GROUP BY months.month
Order BY FIELD(MONTH,'January','February','March','April', 'May', 'June', 'Jully', 'August', 'September', 'October', 'November', 'December')
The month() function returns a number, as opposed to the name of the month.
Either use the monthname() function or store the months' number in your helper table as opposed to the name of the month. The latter is slightly more reliable, since the language setting of mysql influences the return value of the monthname() function.

Select multiple years in separate columns

I have a table that stores the date and price of purchases.
For example
date | price
---------------------
2014-1-12 | 6.50
2014-2-34 | 10.99
2015-1-01 | 3.22
2015-2-14 | 4.12
And so on.
What I want to achieve: A query that outputs the SUM of the purchases grouped per month of the year.
The IMPORTANT thing is, though, that I need to have the different years in COLUMNS to be able to make a graph with a separate line for each year. So the output I need is this:
MONTH | 2014 | 2015
JAN | 123.23 | 99.1
FEB | 457.00 | 122.00
MAR | 299.99 | 789.12
... |
NOV | 333.33 | 10.99
DEC | 100.00 | 20.10
Is this even possible? I searched quite a long time for things like "year on year" query etc. But I could not find anything.
Any help is greatly appreciated!
Just use conditional aggregation:
select monthname(date) as mon,
sum(case when year(date) = 2014 then price else 0 end) as price_2014,
sum(case when year(date) = 2015 then price else 0 end) as price_2015
from table t
group by monthname(date)
order by max(month(date));

mysql complex query for monthly report

employee makes entry in the following table when starting new task
from home or office
[tablename=CHECK]
c_id c_sdate c_emp c_task
-------------------------------------------------
1 2013-05-01 01:01:00 1 26 //date 01 from home-----
2 2013-05-01 08:11:00 1 27 //date 01 from office--- Present
3 2013-05-02 03:41:00 1 28 //date 02 from home---
4 2013-05-02 09:12:00 1 29 //date 02 from office-
5 2013-05-02 22:32:00 1 30 //date 02 from home---Present
6 2013-05-03 01:43:00 1 31 //date 03 from home
7 2013-06-03 23:25:00 1 32 //date 03 from home----------Homework
8 2013-06-03 02:15:00 2 33 //other employee
an employe will be considered as present if there 1 or many records where time between 8am and 8pm
an employe will be considered as workedFromHome if there 1 or many records where time NOT between 8am and 8pm, and not present on that day
note: do not count a day as workedFromHome if there is any record time between 8am and 8pm (means workedFromHome is only counted if he is not resent on that day)
I want to display monthly report of a employee eg. c_emp=1 for month eg. 5
like this in 1 query
c_emp presentCount HW_Count
1 3 1
or separatly query 1
c_emp presentCount
1 3
and query 2
c_emp HW_Count
1 1
I have tried for counting present working fine
select count(distinct(date_format(c_sdate,'%e'))) as count
from ita_check
where date_format(c_sdate,'%m')=5
and c_emp=1
and date_format(c_sdate,'%H%i')>=800
and date_format(c_sdate,'%H%i')<=2000
and for counting fromHome giving wrong count
select count(distinct(date_format(c_sdate,'%e'))) as count
from ita_check
where date_format(c_sdate,'%m')=5
and c_eid=1
and c_id not in (
select c_id
from ita_check
where date_format(c_sdate,'%m')=5
and c_eid=1
and (date_format(c_sdate,'%H%i')<=800 or date_format(c_sdate,'%H%i')>=2000)
)
and date_format(c_sdate,'%H%i')<800
or date_format(c_sdate,'%H%i')>2000
in above query for counting Working
the sub query returns 1 and 2
while the outer eliminate c_id=2 but not c_id=1
Try this query
SELECT c_emp,
sum(if(cnt>=1,1,0)) as Office,
count(*)-sum(if(cnt>=1,1,0)) as WFH from (
select c_emp, Date(c_sdate),
sum(if(c_sdate BETWEEN Date(c_sdate) + interval 8 hour
AND Date(c_sdate) + interval 20 hour, 1, 0)) as cnt
from table1
group by c_emp, Date(c_sdate)) tmp
group by c_emp
SQL FIDDLE:
| C_EMP | OFFICE | WFH |
------------------------
| 1 | 2 | 2 |
| 2 | 0 | 1 |
For monthly report
SELECT c_emp, date_format(c_date, '%c %Y') as Mnth,
sum(if(cnt>=1,1,0)) as Office,
count(*)-sum(if(cnt>=1,1,0)) as WFH from (
select c_emp, Date(c_sdate) as c_date,
sum(if(c_sdate BETWEEN Date(c_sdate) + interval 8 hour
AND Date(c_sdate) + interval 20 hour, 1, 0)) as cnt
from table1
group by c_emp, Date(c_sdate)) tmp
group by c_emp,Mnth
SQL FIDDLE:
| C_EMP | MNTH | OFFICE | WFH |
---------------------------------
| 1 | 5 2013 | 2 | 1 |
| 1 | 6 2013 | 0 | 1 |
| 2 | 6 2013 | 0 | 1 |

How to add time in sql server 2008?

I want to calculate total hrs spend by an employee between 09:00am and 18:00pm.
My database look like this.
How can I do this??
AttendanceId EmpId CheckTime CheckType
-------------------------------------------------------------------------
3 5 2013-01-03 09:00:15.000 1 (Login)
4 5 2013-01-03 11:00:00.000 2 (Logout)
5 5 2013-01-03 11:30:00.000 1
6 5 2013-01-03 13:00:00.000 2
7 5 2013-01-03 13:30:00.000 1
8 5 2013-01-03 16:00:00.000 2
9 5 2013-01-03 16:30:00.000 1
10 5 2013-01-03 18:00:00.000 2
Since your Login/Logout values are in the same column, this might be easier to PIVOT the login/logout times first then get the datediff to determine the total amount of time an employee is present.
The PIVOT portion of the query is this:
select empid, [1], [2]
from
(
select empid, checktime, checktype,
row_number() over(partition by empid, checktype order by checktime) rn
from yourtable
) src
pivot
(
max(checktime)
for checktype in ([1], [2])
) piv
See SQL Fiddle with Demo
The result of this is:
| EMPID | 1 | 2 |
---------------------------------------------------------------------------
| 5 | January, 03 2013 09:00:15+0000 | January, 03 2013 11:00:00+0000 |
| 5 | January, 03 2013 11:30:00+0000 | January, 03 2013 13:00:00+0000 |
| 5 | January, 03 2013 13:30:00+0000 | January, 03 2013 16:00:00+0000 |
| 5 | January, 03 2013 16:30:00+0000 | January, 03 2013 18:00:00+0000 |
Once the data is in this structure, you can easily get the difference in the time by applying the DateDiff() function.
The final query to generate the amount of time an employee is logged in is:
select empid, sum(SecondsDiff) / 3600 as TotalHours
from
(
select empid, datediff(ss, [1], [2]) SecondsDiff
from
(
select empid, checktime, checktype,
row_number() over(partition by empid, checktype order by checktime) rn
from yourtable
) src
pivot
(
max(checktime)
for checktype in ([1], [2])
) piv
) src
group by empid
See SQL Fiddle with Demo
And the result is:
| EMPID | TOTALHOURS |
----------------------
| 5 | 7 |
To get the difference between two dates, you use the DATEDIFF function:
http://msdn.microsoft.com/en-us/library/ms189794.aspx
I think you'd need to do this row-by-row, though. Because of the structure of your table, you can't just do a simple query.