I am facing issue while joining the three table Employee,Eventcelibration,emp_event.
Employee table has three fields birth_date,date_of_joining,Anniversary_date.
want to make a query on basis of above three column.if employee has birthday then select the birth_day description from other table eventcelibration and if he has joining date today then select joining message from the table. like wise.
made the query on some dummy data as below.
Employee table
id
employee_id
name
designation
contactno
email
birth_date
date_of_joining
Table eventcelibration
Event_cl_id
Event_type
frequency
description
template
subject
Third Table
Emp_event
Event_id
employee_id.
I have tried the query,
select a.employee_id,a.name,a.email,a.birth_date,c.template,c.description,c.subject,c.event_type from
employee a inner join emp_event b on a.id = b.Event_id
inner join eventcelebration c on b.employee_id = c.event_cl_id
where CAST(birth_date as date) = CAST(curdate() as date) or CAST(date_of_joining as date) = CAST(curdate() as date)
It returns us the three result but I want only one that is birthday , because birthday is today date.
You are considering date datatype, which includes year.
In this case for an yearly event only month and day of month matters not the year.
I hope the following query would help
SELECT a.employee_id,a.name,a.email,a.birth_date,c.template,c.description,c.subject,c.event_type FROM
employee a INNER JOIN emp_event b ON a.id = b.Event_id
INNER JOIN eventcelebration c ON b.employee_id = c.event_cl_id
WHERE DATE_FORMAT(birth_date,'%m-%d') = DATE_FORMAT(CURDATE(),'%m-%d')
OR DATE_FORMAT(date_of_joining,'%m-%d') = DATE_FORMAT(CURDATE(),'%m-%d');
Hope this helps
Select a.birth_date only in the select query.
select a.birth_date from
employee a inner join emp_event b on a.id = b.Event_id
inner join eventcelebration c on b.employee_id = c.event_cl_id
where CAST(birth_date as date) = CAST(curdate() as date) or CAST(date_of_joining as date) = CAST(curdate() as date)
Related
I'm fairly new to SQL and I'm trying get total orders by new customers every day and each week in Mysql ( feel free to answer in any sql versions). First I tried to get total orders by new customers every day by writing below query, however Im getting incorrect results.
select COUNT(u.orderId), date(u.createdAt) as ord_dt, u.userId
from userorder u
inner join
(
select userId, min(date(createdAt)) as first_date
from userorder
group by 1
) g
on g.userId = u.userId
where g.first_date < date(u.createdAt)
group by 3
Link to the dataset https://docs.google.com/spreadsheets/d/1fA6hAkDJgp28BF0G0aSe9Ml64S9cIwch/edit?usp=sharing&ouid=104686423957654811582&rtpof=true&sd=true
Any help is appreciated
I wrote this query to get the daily answer.
select first_order_date, sum(first_total_order) as tot from
(select user_id,min(order_date) as first_order_date,total_order as
first_total_order
from
(select userId as user_id,date(createdAt) as order_date,count(orderId)
as total_order
from userorder
group by 1,2
) as uo
group by 1) z
group by 1;
i have two tables
Companies
company_payments
each company is doing two types of payments vat and witholding_tax, i am doing following query which returns me company's last payments for the current year
SELECT * FROM companies c
JOIN ( SELECT MAX(id) max_id, company_id FROM company_payments )
c_max ON (c_max.company_id = c.id)
JOIN company_payments cp ON (cp.id = c_max.max_id)
WHERE
YEAR(cp.last_payment) = YEAR(CURDATE())
Below is the structure of my company_payments table
Now instead of returning one last payment i want to return last payment for payment type 'vat' and 'witholding_tax' both , if its not there would need an empty record ,
Could someone please advise me how can i achieve this
You can use a correlated subquery:
select cp.*
from company_payments cp
where cp.last_payment = (select max(cp2.last_payment)
from company_payments cp2
where cp2.company_id = cp.company_id and
cp2.payment_type = cp.payment_type
);
If you want to filter only on the most recent year, you can add the date filter to the outer query.
Given two tables, orders (order_id, date, $, customer_id) and customers (ID, name)
Here's my method but I'm not sure if it's working & I'd like to know if there's faster/better way of solving these problems:
1) find out number of customers who made at least one order on date 7/9/2018
Select count (distinct customer_id)
From
(
Select customer_id from orders a
Left join customer b
On a.customer_id = b.ID
Group by customer_id,date
Having date = 7/9/2018
) a
2) find out number of customers who did not make an order on 7/9/2018
Select count (customer_id) from customer where customer_id not in
(
Select customer_id from orders a
Left join customer b
On a.customer_id = b.ID
Group by customer_id,date
Having date = 7/9/2018
)
3) find the date with most sales between 7/1 and 7/30
select date, max($)
from (
Select sum($),date from orders a
Left join customer b
On a.customer_id = b.ID
Group by date
Having date between 7/1 and 7/30
)
Thanks,
For problem 1, a valid solution might look like this:
SELECT COUNT(DISTINCT customer_id) x
FROM orders
WHERE date = '2018-09-07'; -- or is that '2018-07-09' ??
For problem 2, a valid solution might look like this:
SELECT COUNT(*) x
FROM customer c
LEFT
JOIN orders o
ON o.customer_id = x.customer_id
AND o.date = '2018-07-09'
WHERE o.crder_id IS NULL;
Assuming there are no ties, a valid solution to problem 3 might look like this:
SELECT date
, COUNT(*) sales
FROM orders
WHERE date BETWEEN '2018-07-01' AND '2018-07-30'
GROUP
BY date
ORDER
BY sales DESC
LIMIT 1;
The default format for a date in MySQL is YYYY-MM-DD, although this can be customized. You have to put quotes around it, otherwise it's treated as an arithmetic expression.
And none of your queries need to join with the customer table. The customer ID is already in the orders table, and you're not returning any info about the customers (like the name or address), you're just counting them.
1) You don't need the subquery or grouping.
SELECT COUNT(DISTINCT customer_id)
FROM orders
WHERE date = '2018-07-09'
2) Again, you don't need GROUP BY in the subquery. There's also a better pattern than NOT IN to get the count of non-matching rows.
SELECT COUNT(*)
FROM customer AS c
LEFT JOIN order AS o on c.id = o.customer_id AND o.date = '2018-07-09'
WHERE o.id IS NULL
See Return row only if value doesn't exist for various patterns to do this.
3) You can't use MAX($) in the outer query because the inner query doesn't return a column with that name. But even if you fix that, it still won't work, because the date column won't necessarily come from the same row that has the maximum. See SQL select only rows with max value on a column for more explanation of this.
You don't need a subquery at all. Use a query that returns the total sales for each day, then use ORDER BY to get the highest one.
SELECT date, SUM($) AS total_sales
FROM orders
WHERE date BETWEEN '2018-07-01' AND '2017-07-30'
GROUP BY date
ORDER BY total_sales DESC
LIMIT 1
If "most sales" is supposed to mean "most number of sales", replace SUM($) with COUNT(*).
i have 3 tables
Employee => e_id (P.K), dep_id (F.k)
Department => d_id (P.K)
Attendance => id (P.K), date_of_absence (DATE), e_id_f (F.K)
i want to get the number of absent employees in certain department for a certain period.
i created a table called MyDates
CREATE TABLE MyDates (mydate date);
and this procedure to fill MyDates Table with Dates
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)
BEGIN
WHILE dateStart <= dateEnd DO
INSERT INTO MyDates (mydate) VALUES (dateStart);
SET dateStart = date_add(dateStart, INTERVAL 1 DAY);
END WHILE;
END;
then i called the procedure to fill MyDates with date CALL filldates('2017-01-01','2017-03-31');
Then i made this select statement :
select mydates.mydate, count(attendance.date_of_absence)
from mydates left join attendance on
mydates.mydate = attendance.date_of_absence
where mydates.mydate Between "2017-01-01" AND "2017-01-31"
group by mydates.mydate
This query gets what i need but for all departments, BUT for a certain department the number of rows is incorrect
select mydates.mydate, count(attendance.date_of_absence)
from mydates
left join attendance on mydates.mydate = attendance.date_of_absence
inner join employee on attendance.e_id_f = employee.e_id
where mydates.mydate Between "2017-01-01" AND "2017-01-31" AND employee.dep_id = 4
group by mydates.mydate;
This is a screenshot
IMG
There are 3 issues with your query I can see. The 1st 2 results in dropping the dates where no matching record is found, the 3rd potentially means that you get wrong counts:
inner join employee on attendance.e_id_f = employee.e_id - if there is no matching record for a day, then attendance.e_id_f will be null for that day. The inner join will eliminate this record from the resultset. Solution: make this join a left as well.
AND employee.dep_id = 4 - this would only keep records in the resultset, that have an employee record associated with it, so if you have a day with 0 absences, this criteria would eliminate it from the resultset. Solution: include this criteria in the join condition.
count(attendance.date_of_absence) - counts occurances from the attendance table, which will not be correct after adding the 2nd left join. Solution: use count(employee.dep_id) instead.
Modified query:
select mydates.mydate, count(employee.dep_id)
from mydates
left join attendance on mydates.mydate = attendance.date_of_absence
left join employee on attendance.e_id_f = employee.e_id AND employee.dep_id = 4
where mydates.mydate Between "2017-01-01" AND "2017-01-31" group by mydates.mydate
Alternative solution is to use nested joins, where you specifically instruct MySQL to execute attendance inner join employee join first. You still need to move the employee.dep_id = 4 condition to the join condition:
select mydates.mydate, count(attendance.date_of_absence)
from mydates
left join (attendance inner join employee)
on mydates.mydate = attendance.date_of_absence
and attendance.e_id_f = employee.e_id
and employee.dep_id = 4
where mydates.mydate Between "2017-01-01" AND "2017-01-31"
group by mydates.mydate
In the latter case the nested inner join ensures that only those attendance records are returned that belong to dep_id = 4 and these records are then left joined to your dates table. In this case there is no need to change the field you are counting.
I have 2 tables: orders and bookings.
The orders table contain unique orders from customers. Each customer has booked a locker for a period of 1 to 5 years and therefore the bookings table can contain 1 to 5 rows pr. order (1 row for each year). Each row in the booking table contains and end_date which is the same date every year (20XX-06-30).
I want to select all the orders where the corresponding final end_date in the bookings table is this year (2014-06-30).
SELECT DISTINCT orders.id
FROM orders,
bookings
WHERE orders.id = bookings.order_id
AND bookings.end_date = '2014-06-30'
The problem with this query is that it also selects the orders where the end_date in the booking rows continue the following years (2015-06-30, 2016-06-30 etc).
I am not sure I understood well, but here's a solution for what I understood, this should get you the order ids where there last end date (max) is 2014-06-30.
SELECT orders.id, MAX(bookings.end_date)
FROM orders INNER JOIN bookings
ON orders.id = bookings.order_id
GROUP BY bookings.order_id
HAVING MAX(bookings.end_date) = '2014-06-30'
Maybe join to the bookings again, checking for a larger booking date for the same order id:-
SELECT orders.id
FROM orders
INNER JOIN bookings ON orders.id = bookings.order_id
LEFT OUTER JOIN bookings2 ON orders.id = bookings2.order_id AND bookings2.end_date > bookings.end_date
WHERE bookings.end_date = '2014-06-30'
AND bookings2.end_date IS NULL