I have two tables. One is an employee table containing the employee information and the other table is the sales the employee has made. I am trying to group the sum of sales made by an employee in a month including the months where he/she has made zero sales. Here are some of the values in the table
Employees table
number name
1 Matt
2 Foggy
3 Karen
4 Wilson
sales
employee_number month sale_number sale_amount
1 January 2015 1 300
1 January 2015 2 50
1 February 2015 1 400
2 March 2015 1 300
3 January 2015 1 50
I was able to write the query for getting the monthly sales sum using the following query
select sum(sales.sale_amount), sales.employee_number, sales.month, sales.sale_number
from sales group by employee_number, month;
Now because I also need the months including zeros I thought left outer join with the different months should do the trick. However the output still consists of the same output from before without zeros or null. Does the left outer join not join the null values?
The output should be something like this.
number name sale_amount sale_month
1 Matt 350 January 2015
1 Matt 400 February 2015
1 Matt 0 March 2015
2 Foggy 0 January 2015
2 Foggy 0 February 2015
2 Foggy 300 March 2015
and so on.
A left outer join conjures up null values for missing rows from the right hand table. To show all months, you'd switch the order of tables:
from months
cross join
employees
left outer join
sales
on sales.month = months.month
and employees.number = sales.employee_number
If you're missing a months table, you can ad-lib one from the sales table:
select months.month
, employees.name
, sum(sale_amount) as sales
from (
select distinct month
from sales
) as months
cross join
employees
left outer join
sales
on sales.month = months.month
and employees.number = sales.employee_number
group by
months.month
, employees.name
Example at SQL Fiddle.
Following query will help you:
SELECT q1.month, q1.number, q2.total_sales FROM
(SELECT distinct s.month, e.number
FROM sales s, Employees e) AS q1
LEFT JOIN
(SELECT SUM(sales.sale_amount) AS total_sales, sales.employee_number, sales.month, sales.sale_number
FROM sales group by employee_number, month) AS q2
ON (q1.month = q2.month) AND (q1.number = q2.employee_number)
ORDER BY month, number;
check the fiddle
Related
I have a MYSQL table like this
person giftaid postcode year amount
A 1 NULL 2010 10
A 0 XY123 2010 15
A 0 NULL 2011 10
A 0 NULL 2011 20
B 0 NULL 2010 20
B 0 NULL 2010 1
B 0 NULL 2011 30
C 1 NULL 2010 50
C 1 AB345 2011 80
And I want to sum the amounts given by each person in each year, but take the giftaid and postcode values for that person from any year. I.e. I need
person ever_giftaided any_postcode year sum
A 1 XY123 2010 25
A 1 XY123 2011 30
B 0 NULL 2010 21
B 0 NULL 2011 30
C 1 AB345 2010 50
C 1 AB345 2011 80
Note that although person A didn't agree to giftaid in 2011, because they agreed in 2010, I'm happy to fill out the ever_giftaided column with a 1 for all years, and take any non-null postcode too.
If I do a simple GROUP BY person, year, and use MAX(giftaid) AS ever_giftaided, MAX(postcode) AS any_postcode, then in the second row, person A gets a 0 for ever_giftaided, and NULL for any_postcode, because the group by clause doesn't transfer information between the groupings by person, but by the groupings of the combinations of person and year. I could simply GROUP BY person, but then I don't get the amounts broken down by year. So how can I do this?
Join two queries. One groups by person, the other groups by person, year.
SELECT t1.person, t1.ever_giftaided, t1.any_postcode, t2.year, t2.sum
FROM (
SELECT person, MAX(giftaided) AS ever_giftaided, MAX(postcode) AS any_postcode
FROM yourTable
GROUP BY person) AS t1
JOIN (
SELECT person, year, SUM(amount) AS sum
FROM yourTable
GROUP BY person, year) AS t2 ON t1.person = t2.person
You can also do one of the groupings in the main query:
SELECT t1.person, MAX(giftaided) AS ever_giftaided, MAX(postcode) AS any_postcode,
t2.year, t2.sum
FROM yourTable AS t1
JOIN (
SELECT person, year, SUM(amount) AS sum
FROM yourTable
GROUP BY person, year) AS t2 ON t1.person = t2.person
GROUP BY t1.person
Im trying to select only ids of customers that have ordered atleast once every year in a specific time period for example 2010 - 2017
example:
1. customer ordered in 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 should be shown
2. customer ordered in 2010, 2011, 2012,2013,2014,2015, 2017 should not be shown
my query counts in all years not within the period
o_id o_c_id o_type o_date
1345 13 TA 2015-01-01
7499 13 TA 2015-01-16
7521 14 GA 2015-01-08
7566 14 TA 2016-01-24
7654 16 FB 2016-01-28
c_id c_name c_email
13 Anderson example#gmail.com
14 Pegasus example#gmail.com
15 Miguel example#gmail.com
16 Megan example#gmail.com
my query:
select c.id, c.name, count(*) as counts, year(o.date)
from orders o
join customer c on o.c_id=c.id
where year(o.date) > 2009
group oy c.id
having count(*) > 7
You need a table with all the years so you can check if user order that year. I create a sample with only two years because that is what in your sample data.
You can use this to create a list of years:
How to get list of dates between two dates in mysql select query
Also I use ranges for years so you can use index at the moment of the join.
If you already have a table users you can replace the subquery
SQL DEMO
SELECT user_id, COUNT(o_id) as total_years
FROM years y
CROSS JOIN (SELECT DISTINCT `o_c_id` as `user_id` FROM `orders`) as users
LEFT JOIN orders o
ON o.`o_date` >= y.`year_begin`
AND o.`o_date` < y.`year_end`
AND o.`o_c_id` = `user_id`
GROUP BY user_id
HAVING total_years = (SELECT COUNT(*) FROM years)
;
I want to join two tables, and display year(date),total and vehicle type.
If year and vehicle_type is the same then their total should be combined. This is my query.
select extract(year from ra.roadAccident_date) as 'Year',
c.casualties_death + c.casualties_serious + c.casualties_minor as 'Total',
ra.vehicle_type as 'Types of Vehicle'
from casualties c
join roadAccidents ra
on (c.accident_id = ra.accident_id)
My results are
Year Total Types of Vehicle
2014 6 taxi
2014 9 lorry
2014 3 bus
2014 16 bus
2015 7 taxi
2015 5 lorry
2015 7 lorry
2016 2 bus
2016 5 lorry
2016 9 bus
For 2014, i want vehicle type bus to be combined to one row with total 19. I tried multiple group by methods but could not find the one I am looking for.
I don't see why a simple GROUP BY won't work:
SELECT
EXTRACT(YEAR FROM ra.roadAccident_date) AS 'Year',
SUM(c.casualties_death + c.casualties_serious + c.casualties_minor) AS 'Total',
ra.vehicle_type AS 'Types of Vehicle'
FROM casualties c
INNER JOIN roadAccidents ra
USING accident_id
GROUP BY ra.vehicle_type, YEAR(ra.roadAccident_date)
Wrap the whole thing (as a subquery) with a grouping outer one, like
Select yr,vtype, sum(total) as tot from
(
select extract(year from ra.roadAccident_date) as yr,
c.casualties_death +c.casualties_serious+c.casualties_minor as total
ra.vehicle_type as vtype
from casualties c
join roadAccidents ra on (c.accident_id = ra.accident_id)
) stats group by yr, vtype
I have two queries that give respectively the number of working unit bought, and the number of working unit consumed by a client.
I am working on a SQL Server 2014
The WUBought query returns something like this example :
Customer Year Month UnitBought
Cust1 2015 6 50
Cust2 2014 7 100
Cust1 2013 10 30
Cust3 2015 2 40
The other query returns the number that were consumed by a client :
Customer Year Month UnitConsumed
Cust1 2015 2 6
Cust1 2015 5 20
Cust2 2015 3 8
Cust1 2015 4 3
Cust3 2015 2 10
What I am basically trying to do, is a sum of what has been bought for every month, minus what has been consumed. Here is an example of what I want as a result for the first six months for Cust1 :
Customer Year Month Remaining
Cust1 2015 1 30
Cust1 2015 2 24
Cust2 2015 3 24
Cust1 2015 4 21
Cust3 2015 5 1
Cust3 2015 6 51
The query that returns the WU bought with a UNION ALL from a table that lists every month, to get each month even if there is no value :
SELECT Customer, [Year], [Month], SUM(UOBought) AS UORest
FROM WU_Bought
GROUP BY [Customer], [PurchaseDate]
UNION ALL
SELECT '' AS Customer, [Year], [Month], '' AS UORest
FROM Months
GROUP BY [Year], [Month]
Here is the query that sums every bought unit every month, with the same union statement :
SELECT Customer, [Year], [Month], SUM(TotalConsumed) * -1 AS UORest
FROM WUConsumed
GROUP BY Customer, Year, Month
UNION ALL
SELECT '' AS Customer, [Year], [Month], '' AS UORest
FROM EveryMonths
GROUP BY Year, Month
Right now I think I must adjust the first one, forcing it to keep the previous sum, but I am not sure how I can do that.
Does this work for you?
SELECT b.customer_id, b.year, b.month, SUM(b.units_bought) AS units_bought, ISNULL(c.units_consumed,0) AS units_consumed, SUM(b.units_bought) - ISNULL(c.units_consumed,0) AS units_remaining
FROM Bought b
LEFT JOIN Consumed c
ON b.customer_id = c.customer_id AND b.year = c.year AND b.month = c.month
GROUP BY b.customer_id, b.year, b.month
Ok, I got it working.
What I did was really "simple", using a SQL Server feature, available since 2012 :
ROWS UNBOUNDED PRECEDING
Here is a pretty clear article about this feature.
I created an other view grouping the results from the queries about consumed and bought units with a UNION ALL clause, called "WU_Closing_View", then used the ROWS UNBOUNDED PRECEDING within it :
SELECT Customer, Year, Month, SUM(Closing) OVER(PARTITION BY Customer ORDER BY Year, Month ROWS UNBOUNDED PRECEDING) AS Closing
FROM WU_Closing_View
GROUP BY Customer, Year, Month, Closing
UNION ALL
SELECT '' AS Customer, Year, Month, '' AS Sum_bought
FROM Months
GROUP BY Year, Month
ORDER BY Customer, Year, Month
Note that I used PARTITION BY, in order to sum by client. Because I wanted to show every month in a SSRS matrix, I added a "UNION ALL" pointing to a table that has every year and month on it for an empty client, from 2010 to 2017. But it is optional if you don't need the evolution for every month.
There may be an easier way, but that's the one I found so far.
i have been stuck on this query where i have to select the employees who are working in company for past 5 years.
e-g
in 2010 1 employee Registered so Total Employees in 2010 1
in 2011 2 employees Registered so Total Emloyees in 2013 3
in 2012 4 employees Registered and 1 left so Total Employees in 2012 6
in 2013 5 employees Registered and 2 left So Total Employees in 2013 9
in 2014 No New employee Registered or Left So Same as Same
etc
So in end employees Report is like
(2010), (2011), (2012), (2013), (2014)
1 3 6 9 9
now i am stucked how can i achieve this in mysql query.
I have table Employee where employee info is registered.
Have Employement Table where if employee is registered then join date is assigned and if left then end date is assigned.
Also There is then gender table to show in year how many males and how many females are working in company.
Finally here is the Query i tried.. but this is not the right query. i am missing something here in the query but i cant quite get that.
SELECT MLGT.`gender_type_title`,MLGT.`gender_type_id` AS GenderID,COUNT(E.`gender`) AS TotalGenders,ET.`joining_date`
FROM employee E
INNER JOIN employment ET
ON E.`employee_id` = ET.`employee_id` AND ET.`current` = 1 AND ET.`trashed`=0
INNER JOIN ml_gender_type MLGT
ON E.`gender` = MLGT.`gender_type_id` AND MLGT.`trashed`=0
WHERE E.`trashed`=0 AND ET.`joining_date` >= DATE_SUB(NOW(),INTERVAL 5 YEAR) AND ET.`current`= 1
GROUP BY E.`gender`, YEAR(ET.`joining_date`);
You need another table (or constant sub query) to have the year list you want to group by. Make a join between this new table and the employment one with a condition on joining date comparison. Then count the results :)
Try This query
SELECT YEAR(ET.`joining_date`) as Year, MLGT.`gender_type_title` as Gender, count(E.employee_id) as Emp_count
FROM employee E
INNER JOIN employment ET
ON E.`employee_id` = ET.`employee_id` AND ET.`current` = 1 AND ET.`trashed`=0
INNER JOIN ml_gender_type MLGT
WHERE E.`trashed`=0 AND ET.`joining_date` >= DATE_SUB(NOW(),INTERVAL 5 YEAR) AND ET.`current`= 1
GROUP BY Year, Gender;