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)
;
Related
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.
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 end up having the same format. Each has a Month, a year, and some relevant data per month/year. The schema looks like this:
subs Month Year
8150 1 2015
11060 1 2016
5 2 2014
6962 2 2015
8736 2 2016
Cans months years
2984 1 2015
2724 1 2016
13 2 2014
2563 2 2015
1901 2 2016
The first query syntax looks like this:
SELECT
COUNT(personID) AS subs_per_month,
MONTH(Date_1) AS month_1,
YEAR(Date_1) AS year_1
FROM
(SELECT
personID, MIN(date) AS Date_1
FROM
orders
WHERE
isSubscription = 1
GROUP BY personID
ORDER BY Date_1) AS my_sub_q
GROUP BY month_1 , year_1
The second query:
SELECT
COUNT(ID), MONTH(date) AS months, YEAR(date) AS years
FROM
orders
WHERE
status = 4 AND isSubscription = 1
GROUP BY months , years
ORDER BY months, years
The end goal is to write a simple join so that the final dataset looks like this:
subs cans months years
8150 2984 1 2015
11060 2724 1 2016
5 13 2 2014
6962 2563 2 2015
8736 1901 2 2016
I'm a little overwhelmed with how to do this correctly, and after a lot of trial and all error, I thought I'd ask for help. What's confusing is where the JOIN goes, and how that looks relative to the rest of the syntax.
Without giving consideration to simplifying your queries you can use your two queries as inline views and simply select from both (I aliased Q1 and Q2 for your queries and named fields the same within each for simplicity.
Select Q1.cnt as Subs, Q2.cnt as Cans, Q1.months, Q1.years
from (SELECT
COUNT(personID) AS Cnt,
MONTH(Date_1) as Months,
YEAR(Date_1) AS years
FROM (SELECT personID, MIN(date) AS Date_1
FROM orders
WHERE isSubscription = 1
GROUP BY personID) AS my_sub_q
GROUP BY month_1 , year_1) Q1
INNER JOIN (SELECT COUNT(ID) cnt, MONTH(date) AS months, YEAR(date) AS years
FROM orders
WHERE status = 4
AND isSubscription = 1
GROUP BY months, years) Q2
ON Q1.Months = Q2.Months
and Q1.Years = Q2.years
Order by Q1.years, Q2.months
Temporary table approach:
create temporary table first_query
<<your first query here>>;
create temporary table second_query
<<your second query here>>;
select fq.subs, sq.cans, fq.months, fq.years
from first_query fq
join second_query sq using (months, years)
Your table preview and query columns do not match for first query, so I assumed both tables have columns - months and years.
One messy query approach:
SELECT fq.subs_per_month subs, sq.cans, sq.months, sq.years
FROM
(SELECT
COUNT(personID) AS subs_per_month,
MONTH(Date_1) AS month_1,
YEAR(Date_1) AS year_1
FROM
(SELECT
personID, MIN(date) AS Date_1
FROM
orders
WHERE
isSubscription = 1
GROUP BY personID
ORDER BY Date_1) AS my_sub_q
GROUP BY month_1 , year_1) fq
JOIN
(SELECT
COUNT(ID) cans, MONTH(date) AS months, YEAR(date) AS years -- I added 'cans'
FROM
orders
WHERE
status = 4 AND isSubscription = 1
GROUP BY months , years
ORDER BY months, years) sq
ON fq.month_1 = sq.months AND fq.year_1 = sq.years
Please use following query
select t1.subs as subs,t2.Cans as cans,t1.months,t1.year as years from table1 t1 inner join
table2 t2 on t1.month=t2.months and t1.year=t2.years
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
I am having a problem with this query:
SELECT
YEAR(passDate) as Year,
count(*) AS total_amount
FROM
`dsp_drop_pass_details`
WHERE passDate
BETWEEN '2009-01-01'
AND '2012-05-01'
AND batch='DROPOUT'
GROUP BY YEAR(passDate)
ORDER BY YEAR(passDate)
output---
Month total amount
2011 30
2012 20
But my desire out put is
Month total amount
2009 0
2010 0
2011 40
2012 20
I want 0 where count is 0
The easiest way would be to have a table Years, with all the wanted years.
create table Years(yearValue int);
insert into years values (2001), (2002)..., (2020);
then do a left join on your actual table.
SELECT y.yearValue, COALESCE(COUNT(d.id), 0) --assumning you have a field id in dsp_drop_pass_details
FROM years y
LEFT join dsp_drop_pass_details d on y.yearValue = YEAR(d.passDate)
WHERE y.yearValue between 2009 and 2012
GROUP BY y.yearValue
ORDER BY y.yearValue;