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
Related
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 am working with a parts / motorcycle fitment Mysql database where all parts are linked to all motorcycles they can be installed on. It looks like this:
part_number motorcycle year
1000 HONDA_CBR1000 2008
1000 HONDA_CBR1000 2009
1000 HONDA_CBR1000 2010
1000 HONDA_CBR1000 2011
1000 HONDA_CBR1000 2012
1000 HONDA_CBR1000 2013
1001 HONDA_CBR600 2008
1001 HONDA_CBR600 2009
1001 HONDA_CBR1000 2008
1001 HONDA_CBR1000 2009
1001 HONDA_CBR1000 2013
So it means that:
part #1000 can be installed on the Honda CBR1000 from 2008 to 2013
part #1001 can be installed on the Honda CBR600 from 2008 to 2009 AND on the Honda CBR1000 from 2008 to 2013.
Unfortunately, the table (which has ~650,000 rows) was not always filled correctly. In this example, you will notice the following lines are missing:
part_number motorcycle year
1001 HONDA_CBR1000 2010
1001 HONDA_CBR1000 2011
1001 HONDA_CBR1000 2012
because the part #1001 which can be installed on the HONDA_CBR1000 from 2008, 2009 and 2013 can also be installed in the "forgotten" years in between (2010, 2011 and 2012).
So the simple query:
SELECT * FROM mytable WHERE motorcycle = 'HONDA_CBR1000' AND year = '2011'
would only retrieve the row for part #1000 (while in reality, part #1001 is also installable on this bike).
in plain English, I guess a query like
SELECT * FROM mytable WHERE motorcycle = 'HONDA_CBR1000'
AND ("minimum year of part_number applicable to HONDA_CBR1000" <= '2011')
AND ("maximum year of part_number applicable to HONDA_CBR1000" >= '2011')
would retrieve all results (1000 and 1001).
But how can I ask that in SQL? Do you think it would too slow?
Thanks for any help!
SELECT part_number, max(year), Min(year)
FROM mytable
WHERE motorcycle = 'HONDA_CBR1000'
Group By part_number
Having Min(year) <= 2011
And max(year) >= 2011
*********************Edit****************
To improve performance, Lets try this,
1)
SELECT part_number
FROM mytable t,
(Select part_number, Min(year) Minyear, max(year) Maxyear
FROM mytable
Group BY part_number) t1
WHERE t.motorcycle = 'HONDA_CBR1000'
AND t.year Between MinYear and Maxyear
AND t.year = '2011'
*********************EDIT 2**********************************
So This is the query that will list out the years that are missed out. You can put the entire query in to a insert statement
SELECT partsnumber , yrs.allyears
FROM (Select max(year) maxyear, min(year) minyear, partsnumber
FROM yourtable
group by partsnumber) q1
(Select 1950+1+b+a*10 as allyears
from (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) a,
(select 0 as b union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) b) y
Where yrs.allyears between maxyear and minyear
MINUS
SELECT partsnumber , yrs.allyears
From yourtable
yrs --> Subquery that generates years from 1950 to 2050 (If you have more years ( beyond 2050 or before 1950 ) then this has to be changed)
Am selecting the years between the min and max years for each productnumber. then with yrs table as reference am finding the years between min and max years.
The result from above query will give all years between min and max. The minus will give the years that are missed
Here is my approach for getting all combinations of parts and motorcycles and the years they have no data.
Generate all the rows for all the years, then filter out the ones you have. The first part uses cross join. The second left join:
select pm.part_number, pm.motorcycle, y.year
from (select part_number, motorcycle, min(year) as miny, max(year) as maxy
from mytable
group by part_number, motorcycle
) pm cross join
(select distinct year
from mytable
) y
on y.year between pm.miny and pm.maxy left join
mytable t
on t.part_number = pm.part_number and t.motorcycle = pm.motorcycle and
t.year = y.year
where y.year is null;
This assumes that all years are in your table, somewhere. The y table is just a list of years, so you can get it from another table or by creating a derived table. The subquery is just a convenient way to get it.
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 want to show these records column wise for particular month and year, like below table format
Source Total
Organic 1252
Paid 121
Email Campaign 121
Total 1494
select Organic,Paid ,EmailCampaign ,Total from tbl_leads where Month='Aug' and Year='2015'
below is sample date
Organic Paid EmailCampaign Total ProjectName Month Year
4444 5555 2222 1111 demo project Feb 2015
1252 121 121 1494 debug test Aug 2015
In Sql Server you can use Cross Apply with Tabled Valued Constructor to unpivot the data
SELECT cs.Source,
cs.Total
FROM tbl_leads
CROSS apply (VALUES ('Organic',Organic),
('Paid',Paid),
('EmailCampaign',EmailCampaign),
('Total',Total)) cs(Source, Total)
WHERE Month = 'Aug'
AND Year = '2015'
Or Generic Sql solution
SELECT 'Organic' AS Source,
Organic AS Total
FROM tbl_leads
UNION ALL
SELECT 'Paid',
Paid
FROM tbl_leads
UNION ALL
SELECT 'EmailCampaign',
EmailCampaign
FROM tbl_leads
UNION ALL
SELECT 'Total',
Total
FROM tbl_leads
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