I have a table auctions and a table lots:
mysql> select id, auction_name, auction_startdate, auction_planned_closedate from auctions;
+----+--------------+---------------------+---------------------------+
| id | auction_name | auction_startdate | auction_planned_closedate |
+----+--------------+---------------------+---------------------------+
| 1 | Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| 2 | Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
| 3 | Auction 3 | 2016-07-01 00:00:00 | 2016-08-30 00:00:00 |
| 4 | Auction 4 | 2016-09-01 00:00:00 | 2016-10-30 00:00:00 |
+----+--------------+---------------------+---------------------------+
mysql> select id, auction_id, lot_name from lots;
+----+------------+----------+
| id | auction_id | lot_name |
+----+------------+----------+
| 1 | 1 | Lot 1 |
| 2 | 1 | Lot 2 |
| 3 | 1 | Lot 3 |
| 4 | 1 | Lot 4 |
| 5 | 1 | Lot 5 |
| 6 | 1 | Lot 6 |
| 7 | 1 | Lot 7 |
| 8 | 2 | Lot 8 |
| 9 | 2 | Lot 9 |
| 10 | 2 | Lot 10 |
| 11 | 3 | Lot 11 |
| 12 | 3 | Lot 12 |
| 13 | 3 | Lot 13 |
| 14 | 3 | Lot 14 |
| 15 | 4 | Lot 15 |
| 16 | 4 | Lot 16 |
+----+------------+----------+
I want to display only the lots for current auctions (which are auctions 1 and 2 in the example), in other words for which the current time is between the 'auction_startdate' and 'auction_planned_closedate'.
So here is what I want to achieve:
+--------------+---------------------+---------------------------+---------+
| auction_name | auction_startdate | auction_planned_closedate | lots_id |
+--------------+---------------------+---------------------------+---------+
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 1 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 2 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 3 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 4 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 5 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 6 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 7 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 8 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 9 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 10 |
+--------------+---------------------+---------------------------+---------+
The following query gets me the current auctions:
mysql> select auction_name, auction_startdate, auction_planned_closedate from auctions where now() >= auction_startdate and now() <= auction_planned_closedate;
+--------------+---------------------+---------------------------+
| auction_name | auction_startdate | auction_planned_closedate |
+--------------+---------------------+---------------------------+
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
+--------------+---------------------+---------------------------+
and then I do an inner join with the 'lots' table:
select auction_name, auction_startdate, auction_planned_closedate, lots.id
from auctions
where now() >= auction_startdate
and now() <= auction_planned_closedate
inner join lots on auctions.id = lots.auction_id;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'inner join lots on auctions.id=lots.auction_id' at
line 1
I'm getting a syntax error which I'm staring blind at for a while.
Wrong order, put the WHERE clause after the JOIN:
select auction_name, auction_startdate, auction_planned_closedate, lots.id
from auctions
inner join lots on auctions.id = lots.auction_id
where now() >= auction_startdate
and now() <= auction_planned_closedate
Your join is in the wrong order:
select a.auction_name, a.auction_startdate, a.auction_planned_closedate, l.id
from auctions a inner join
lots l
on a.id = l.auction_id
where now() >= a.auction_startdate and now() <= a.auction_planned_closedate ;
Notes:
where goes after the from clause. join is not a separate clause; it is an operator in the from clause.
Table aliases make a query easier to write and to read.
Qualify all the column names. This makes it clear where the columns are coming from.
Related
I have two tables, One is calendar and second is final_registration as follow:
My Calendar table:
*--------------------*
| S.No. | datefield |
*--------------------*
| 1 | 2019-01-01 |
| 2 | 2019-01-02 |
| 3 | 2019-01-03 |
| 4 | 2019-01-04 |
| 5 | 2019-01-05 |
| 6 | 2019-01-06 |
| 7 | 2019-01-07 |
| 8 | 2019-01-08 |
| 9 | 2019-01-09 |
| 10 | 2019-01-10 |
| 11 | 2019-01-11 |
| 12 | 2019-01-12 |
| 13 | 2019-01-13 |
| 14 | 2019-01-14 |
| 15 | 2019-01-15 |
| 16 | 2019-01-16 |
| 17 | 2019-01-17 |
| 18 | 2019-01-18 |
| 19 | 2019-01-19 |
| 20 | 2019-01-20 |
| 21 | 2019-01-21 |
| 22 | 2019-01-22 |
| 23 | 2019-01-23 |
| 24 | 2019-01-24 |
| 25 | 2019-01-25 |
| 26 | 2019-01-26 |
| 27 | 2019-01-27 |
| 28 | 2019-01-28 |
| 29 | 2019-01-29 |
| 30 | 2019-01-30 |
| 31 | 2019-01-31 |
---------------------
My Second table:
*-----------------------------------------*
| id | event_id | name | booking_date |
*-----------------------------------------*
| 1 | 101 | Ritu | 2019-01-15 13:21 |
| 2 | 101 | Seeta | 2019-01-15 18:21 |
| 3 | 101 | Geeta | 2019-01-16 13:21 |
| 4 | 102 | Wasim | 2019-01-16 14:21 |
| 5 | 102 | Rahul | 2019-01-17 13:21 |
| 6 | 101 | Gagan | 2019-01-17 14:21 |
| 7 | 101 | Sunny | 2019-01-17 15:21 |
| 8 | 101 | Aman | 2019-01-17 16:21 |
-------------------------------------------
I am trying below output:
*--------------------*
| datefield | count |
*--------------------*
| 2019-01-01 | 0 |
| 2019-01-02 | 0 |
| 2019-01-03 | 0 |
| 2019-01-04 | 0 |
| 2019-01-05 | 0 |
| 2019-01-06 | 0 |
| 2019-01-07 | 0 |
| 2019-01-08 | 0 |
| 2019-01-09 | 0 |
| 2019-01-10 | 0 |
| 2019-01-11 | 0 |
| 2019-01-12 | 0 |
| 2019-01-13 | 0 |
| 2019-01-14 | 0 |
| 2019-01-15 | 2 |
| 2019-01-16 | 1 |
| 2019-01-17 | 3 |
---------------------
So as today 17-Jan so i need output till current date. I have tried query but it is not given me 01-Jan to 14-Jan
SELECT calendar.datefield, COUNT(calendar.datefield)
FROM calendar
LEFT JOIN final_registration
ON DATE_FORMAT(calendar.datefield, '%Y-%m-%d') = DATE_FORMAT(final_registration.booking_date, '%Y-%m-%d')
WHERE DATE_FORMAT(calendar.datefield, '%Y-%m-%d') <= DATE_FORMAT( CURDATE(), '%Y-%m-%d' )
AND DATE_FORMAT(calendar.datefield, '%Y-%m') = DATE_FORMAT( CURDATE(), '%Y-%m' )
AND final_registration.event_id = '101'
GROUP BY DATE_FORMAT(calendar.datefield, '%Y-%m-%d')
My query gave me below result:
*--------------------*
| datefield | count |
*--------------------*
| 2019-01-15 | 2 |
| 2019-01-16 | 1 |
| 2019-01-17 | 3 |
*--------------------*
I have tried lots but not able to get my result.
You are making your LEFT join into an INNER join by including criteria in the WHERE clause. Try this:
SELECT calendar.datefield, COUNT(calendar.datefield)
FROM calendar
LEFT JOIN final_registration
ON DATE_FORMAT(calendar.datefield, '%Y-%m-%d') = DATE_FORMAT
(final_registration.booking_date, '%Y-%m-%d')
AND final_registration.event_id = '101'
WHERE DATE_FORMAT(calendar.datefield, '%Y-%m-%d') <= DATE_FORMAT( CURDATE(), '%Y-%m-%d' )
AND DATE_FORMAT(calendar.datefield, '%Y-%m') = DATE_FORMAT( CURDATE(), '%Y-%m' )
GROUP BY DATE_FORMAT(calendar.datefield, '%Y-%m-%d')
You need to move some of the restrictions in the WHERE clause to the ON clause:
SELECT
c.datefield,
COUNT(f.booking_date) AS cnt
FROM calendar c
LEFT JOIN final_registration f
ON c.datefield = DATE(f.booking_date) AND
f.event_id = '101'
WHERE
c.datefield BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01') AND CURDATE()
GROUP BY
c.datefield;
Demo
Note that you want to count a field from the final_registration table, which appears on the right side of the left join.
The delay in my answer was due to cleaning up your query to remove all the unneeded calls to DATE_FORMAT. You should be able to deal directly with the datefield. As for the WHERE clause, it seems that you just want dates which are in the current month, but no later than the current day in the month.
I'm having difficulties with creating a sql query that selects a joining of 2 tables where the relationship doesn't exists in a third table.
To be more specific I try to explain it with an example.
I have a table member, form and member_form.
When a member inserts an answer in the form, it's saved in the member_form table.
The forms can be active, and have a deadline.
So what I want is to return a result for each member and the form he still didn't fill in. But the form must be active, and deadline must be for example 2018-03-15. I don't know the amount of members or forms. So I can't say from select * where member id is = x.
This is needed to send a reminder mail to all the users that didn't fill in the form yet for a specific date.
member
id | name | email
--------------------------
1 | Test | test#email.com
2 | test2 | test2#email.com
4 | test4 | test4#email.com
5 | test5 | test5#email.com
6 | test6 | test6#email.com
7 | test7 | test7#email.com
form
id | insert_date | deadline_date | active
---------------------------------------------------------------
1 | 2018-03-15 00:00:00 | 2018-03-15 00:00:00 | 1
2 | 2018-02-10 00:00:00 | 2018-05-15 00:00:00 | 0
3 | 2018-03-15 00:00:00 | 2018-03-15 00:00:00 | 1
5 | 2018-03-15 00:00:00 | 2018-06-15 00:00:00 | 1
6 | 2018-03-15 00:00:00 | 2018-05-15 00:00:00 | 1
7 | 2018-03-15 00:00:00 | 2018-04-15 00:00:00 | 0
member_form
member_id | form_id | answer
--------------------------------------
1 | 6 | 1
1 | 2 | 2
1 | 5 | 1
2 | 2 | 1
2 | 3 | 1
4 | 6 | 2
5 | 6 | 3
5 | 7 | 2
6 | 1 | 2
7 | 2 | 1
Result
member_id | name | email | form_id | insert_date | deadline_date | active
-------------------------------------------------------------------------------------------------------------------
2 | test2 | test2#email.com | 6 | 2018-03-15 00:00:00 | 2018-05-15 00:00:00 | 1
6 | test6 | test6#email.com | 6 | 2018-03-15 00:00:00 | 2018-05-15 00:00:00 | 1
7 | test7 | test7#email.com | 6 | 2018-03-15 00:00:00 | 2018-05-15 00:00:00 | 1
SELECT * FROM form AS f , member AS m WHERE f.deadline_date = '2018-05-15 00:00:00' AND f.active = 1 and !exists(select * FROM member_form AS amf WHERE amf.member_id = am.id And amf.form_id = af.id);
Try this
SELECT * FROM Member m, Form f
WHERE CONCAT(m.id,':',f.id) NOT IN
(SELECT CONCAT(mf.member_id, ':', mf.form_id) FROM Member_form mf)
AND f.deadline_date = '2018-05-15'
AND f.active = 1
I have the following structure
----------
presences
----------
id
started
ended
user_id
---------
breaks
---------
id
presence_id
started
ended
I need to create an SQL query that returns me the following information
presence_id user_id presence_time breaks_time
where presence time is (presence.ended - presence-started) - sum of (break.ended - break.started) of all the breaks related to the presence
Is there an efficient way to get this information with an sql query?
If you know how to do it in eloquent it would be even better :D
Thank you so much!
http://sqlfiddle.com/#!9/650a2/3
SELECT p.id presence_id,
p.user_id,
(p.ended-p.started) presence_time ,
SUM(b.ended-b.started) breaks_time
FROM presences p
LEFT JOIN breaks b
ON p.id = b.presence_id
GROUP BY p.id
UPDATE Same query grouped by user_id:
http://sqlfiddle.com/#!9/1ce21/1
SELECT
sub_total.user_id,
SUM(sub_total.presence_time) ,
SUM(sub_total.breaks_time)
FROM (
SELECT p.id presence_id,
p.user_id,
(p.ended-p.started) presence_time ,
SUM(b.ended-b.started) breaks_time
FROM presences p
LEFT JOIN breaks b
ON p.id = b.presence_id
GROUP BY p.id) sub_total
GROUP BY sub_total.user_id
If your started and ended are stored as datetime or timestamp, then you can easily do the calculation and find the data in minutes.
The following example will be useful when someone taking multiple short breaks through out the working hours.
Later in the application level you can convert the minutes to hour. Here is how you can do in mysql
mysql> select * from presence ;
+------+---------------------+---------------------+---------+
| id | started | ended | user_id |
+------+---------------------+---------------------+---------+
| 1 | 2015-01-01 09:00:00 | 2015-01-01 18:00:00 | 10 |
| 2 | 2015-01-01 09:20:00 | 2015-01-01 18:04:00 | 11 |
| 3 | 2015-01-01 09:10:00 | 2015-01-01 18:30:00 | 12 |
| 4 | 2015-01-02 09:23:10 | 2015-01-02 18:10:00 | 10 |
| 5 | 2015-01-02 09:50:00 | 2015-01-02 19:00:00 | 11 |
| 6 | 2015-01-02 09:10:00 | 2015-01-02 18:36:30 | 12 |
+------+---------------------+---------------------+---------+
6 rows in set (0.00 sec)
mysql> select * from breaks ;
+------+-------------+---------------------+---------------------+
| id | presence_id | started | ended |
+------+-------------+---------------------+---------------------+
| 1 | 1 | 2015-01-01 12:00:00 | 2015-01-01 12:20:30 |
| 2 | 1 | 2015-01-01 15:46:30 | 2015-01-01 15:54:26 |
| 3 | 2 | 2015-01-01 11:26:30 | 2015-01-01 11:34:23 |
| 4 | 2 | 2015-01-01 14:06:45 | 2015-01-01 14:10:20 |
| 5 | 2 | 2015-01-01 16:01:10 | 2015-01-01 16:14:57 |
| 6 | 3 | 2015-01-01 12:11:20 | 2015-01-01 12:40:05 |
| 7 | 3 | 2015-01-01 17:01:10 | 2015-01-01 17:24:21 |
| 8 | 4 | 2015-01-02 12:50:00 | 2015-01-02 13:40:00 |
| 9 | 5 | 2015-01-02 12:20:00 | 2015-01-02 13:05:30 |
| 10 | 5 | 2015-01-02 17:03:00 | 2015-01-02 17:20:00 |
| 11 | 6 | 2015-01-02 12:16:50 | 2015-01-02 12:58:30 |
+------+-------------+---------------------+---------------------+
11 rows in set (0.00 sec)
select
p.id as presence_id,
p.user_id,
timestampdiff(minute,started,ended) - b.break_time as presence_time,
b.break_time from presence p
left join (
select
presence_id,
coalesce(sum( timestampdiff(minute,started,ended ) ),0) as break_time
from breaks
group by presence_id
)b
on b.presence_id = p.id
+-------------+---------+---------------+------------+
| presence_id | user_id | presence_time | break_time |
+-------------+---------+---------------+------------+
| 1 | 10 | 513 | 27 |
| 2 | 11 | 501 | 23 |
| 3 | 12 | 509 | 51 |
| 4 | 10 | 476 | 50 |
| 5 | 11 | 488 | 62 |
| 6 | 12 | 525 | 41 |
+-------------+---------+---------------+------------+
6 rows in set (0.00 sec)
Thanks to #Alex I got it working, my final query is the following (using timestamps)
SELECT *,
TIME_TO_SEC(TIMEDIFF(p.ended,p.started)) as presence_time,
sum(TIME_TO_SEC(TIMEDIFF(b.ended,b.started))) as breaks_time
FROM presences p
left join presences_breaks b on b.presence_id = p.id
group by p.id
I don't know if this is something I can achieve effectively with sub queries, or how to even build a query for this. I have to extract some knowledge about people no longer using our system. Imagine we have 3 users with user id 1024, 1234, and 5678; and User 1024 and 1234 are using theme A, and 5678 is using theme B:
$ SELECT * FROM user; | $ SELECT * FROM user_theme;
+------+------+ | +------+-------+
| id | name | | | user | theme |
+------+------+ | +------+-------+
| 1024 | John | | | 1024 | A |
| 1234 | Jane | | | 1234 | A |
| 5678 | Jeff | | | 5678 | B |
+------+------+ | +------+-------+
The usage tracking table appears as this:
$ SELECT * FROM user_usage;
+----+------+---------------------+------+
| id | user | date | uses |
+----+------+---------------------+------+
| 1 | 1234 | 2014-08-02 00:00:00 | 5 |
| 2 | 1234 | 2014-08-03 00:00:00 | 5 |
| 3 | 1234 | 2014-08-04 00:00:00 | 3 |
| 4 | 1234 | 2014-08-05 00:00:00 | 6 |
| 5 | 1024 | 2014-08-02 00:00:00 | 8 |
| 6 | 1024 | 2014-08-03 00:00:00 | 7 |
| 7 | 1024 | 2014-08-04 00:00:00 | 4 |
| 8 | 1024 | 2014-08-05 00:00:00 | 6 |
| 9 | 1024 | 2014-09-02 00:00:00 | 1 |
| 10 | 1024 | 2014-09-03 00:00:00 | 2 |
| 11 | 1024 | 2014-09-04 00:00:00 | 3 |
| 12 | 1024 | 2014-09-05 00:00:00 | 4 |
| 13 | 5678 | 2014-08-02 00:00:00 | 8 |
| 14 | 5678 | 2014-08-03 00:00:00 | 7 |
| 15 | 5678 | 2014-08-04 00:00:00 | 4 |
| 16 | 5678 | 2014-08-05 00:00:00 | 6 |
| 17 | 5678 | 2014-09-02 00:00:00 | 1 |
| 18 | 5678 | 2014-09-03 00:00:00 | 2 |
| 19 | 5678 | 2014-09-04 00:00:00 | 3 |
| 20 | 5678 | 2014-09-05 00:00:00 | 4 |
+----+------+---------------------+------+
I want to find out the break down to see how many usage have dropped from our system in 2014-09 (aka: have usage data in 2014-08, but no longer in 2014-09), grouped by the theme. So I want to write something like:
SELECT
user_theme.theme,
SUM(user_usage.users) 'uses lost'
FROM
user_theme
LEFT JOIN user_usage
ON user_theme.user = user_usage.user
WHERE
...
GROUP BY
user_theme.theme
# HAVING ...?
And get result such as:
+-------+-----------+
| theme | uses lost |
+-------+-----------+
| A | 19 |
| B | 0 |
+-------+-----------+
Where the 19 comes from SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 8.
I don't know I care about the SUM(uses) from user = 1234 in advance, because I only know I need to include user 1234 in the SUM(uses)'s WHERE clause because SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 9 is 0.
There's actually a lot of users, and a handful of themes (around 20K users, and about 10 themes), so ideally, I think I'd like to avoid doing the filtering in code as opposed to directly in the database. Is there a way to do this effectively in MySQL using raw SQL queries?
Here is query which compares current month with previous one:
set #current_month = now();
set #previous_month = date_sub(#current_month, interval 1 month);
set #current_month = concat(year(#current_month), month(#current_month));
set #previous_month = concat(year(#previous_month), month(#previous_month));
select a.`theme`, sum(ifnull(b.uses_lost,0)) as uses_lost
from
`user_theme` as a
left outer join
(
select `user`, sum(uses) as uses_lost
from `user_usage`
where concat(year(`date`), month(`date`)) = #previous_month
and `user` not in (
select `user`
from `user_usage`
where concat(year(`date`), month(`date`)) = #current_month)
group by `user`
) as b
on (a.`user`=b.`user`)
group by a.`theme`;
fiddle for play
main idea is to find all users who used system during last month and has no rows during current month
let's assume i have follow table
| ID | teamid | timestamp |
| 5 | 1 | 2013-07-27 10:19:00 |
| 6 | 2 | 2013-07-27 10:20:00 |
| 7 | 1 | 2013-07-27 10:25:00 |
| 8 | 3 | 2013-07-27 10:26:00 |
| 9 | 1 | 2013-07-27 10:28:00 |
| 10 | 2 | 2013-07-27 10:29:00 |
| 11 | 3 | 2013-07-27 10:30:00 |
| 13 | 3 | 2013-07-27 10:31:00 |
What i need is the records where the interval between the timestamp is lower then 4 minutes and grouped by the team id
so output need looks like
| 7 | 1 | 2013-07-27 10:25:00 |
| 9 | 1 | 2013-07-27 10:28:00 |
| 11 | 3 | 2013-07-27 10:30:00 |
| 13 | 3 | 2013-07-27 10:31:00 |
can someone show me the correct way to solve
tnx
The following sql statement will return your desired list:
SELECT table1.id, table1.teamid, table1.timestamp
FROM exampleTable table1, exampleTable table2
where table1.id != table2.id AND
table1.teamid = table2.teamid AND
ABS(table1.timestamp - table2.timestamp) < 400
ORDER BY teamid, id