MySql select joined rows that don't exists in third table - mysql

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

Related

mysql query sum values group by month but divided in years

I have a table with 4 columns: ID, fieldDATE, fieldINT1, fieldINT2.
Table is like this:
ID| fieldDate | FieldINT1 | FiledINT2 |
===================================
1 | 2016-01-01 | 100 | 1 |
2 | 2016-01-08 | 200 | 1 |
3 | 2016-02-01 | 150 | 1 |
4 | 2016-02-05 | 400 | 2 |
5 | 2017-01-01 | 120 | 1 |
6 | 2017-01-21 | 123 | 1 |
7 | 2017-02-03 | 30 | 1 |
8 | 2018-01-01 | 123 | 1 |
9 | 2018-01-03 | 30 | 1 |
I'd like to create a table with 12 rows, with the first column is the month name, and the other columns are sum of fieldINT1 and fieldINT2, group by month in a specific YEAR. So in my example, there will be 4 columns ( MONTH NAME, 2016, 2017, 2018)
How can I do it?

mysql - return zero if no results for a given period

I have this table:
+----+--------+------------+-----------+------------------+
| id | amount | period | player_id | payment_category |
+----+--------+------------+-----------+------------------+
| 3 | 100 | 2017-06-01 | 1 | 1 |
| 10 | 100 | 2017-06-01 | 2 | 1 |
| 6 | 100 | 2017-08-01 | 2 | 1 |
| 5 | 100 | 2017-10-01 | 3 | 1 |
| 2 | 100 | 2017-11-01 | 2 | 1 |
| 4 | 100 | 2017-11-01 | 1 | 1 |
| 1 | 100 | 2017-12-01 | 1 | 1 |
| 7 | 100 | 2017-12-01 | 1 | 1 |
| 9 | 100 | 2017-12-01 | 2 | 1 |
| 11 | 200 | 2017-12-01 | 1 | 3 |
+----+--------+------------+-----------+------------------+
Current result:
2017-06-01 2
2017-08-01 1
2017-10-01 1
2017-11-01 2
2017-12-01 3
Desired result:
2017-06-01 2
2017-07-01 0
2017-08-01 1
2017-09-01 0
2017-10-01 1
2017-11-01 2
2017-12-01 3
How can I do that? I tried with coalesce and ifnull. No luck.
I started with DQL:
$query = $em->createQuery('
SELECT COUNT(p.id) as total, p.period
FROM AppBundle:Payment p
WHERE p.period >= :fromTime
AND p.period <= :toTime
AND p.paymentCategory = 1
GROUP BY p.period
')
Of course this does not return the results for missing months ;) I'm looking for a method (doctrine or native mysql) which will somehow fill in the missing months. They can't be hardcoded - I need the results from last x months. Is it even possible or I should do it in PHP?

SQL Query: find lots that belong to current auction

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.

MySQL query to meet specific needs

My table is as follow:
-------------------------------------------
| rec_id | A_id | B_id |Date(YYYY-MM-DD)|
-------------------------------------------
| 1 | 1 | 6 | 2014-01-01 |
| 2 | 5 | 1 | 2014-01-02 |
| 3 | 2 | 6 | 2015-01-03 |
| 4 | 6 | 1 | 2014-01-04 |
| 5 | 7 | 1 | 2014-01-05 |
| 6 | 3 | 6 | 2014-01-06 |
| 7 | 8 | 1 | 2014-01-07 |
| 8 | 4 | 6 | 2014-01-08 |
| 9 | 9 | 1 | 2014-01-09 |
| 10 | 10 | 21 | 2014-01-10 |
| 11 | 12 | 21 | 2014-01-11 |
| 12 | 11 | 2 | 2014-01-12 |
| 13 | 1 | 1 | 2014-12-31 |
| 14 | 2 | 2 | 2014-12-31 |
| 15 | 1 | 1 | 2015-01-31 |
| 16 | 10 | 21 | 2015-01-31 |
| 17 | 1 | 21 | 2014-10-31 |
This table represents the possession of various "A_id" to a specific "B_id" with a date when it is possessed. The possession of each "A_id" can be changed later on at any time. That means the only the latest possession is considered.
I want to find out all the "A_id" that are currently (possessed in latest date) in possession of a specific "B_id". For example, for "B_id" = 6 the possessed "A_id" at present are as follows:
---------------------------
| A_id | Date(YYYY-MM-DD) |
---------------------------
| 2 | 2015-01-03 |
| 3 | 2014-01-06 |
| 4 | 2014-01-08 |
Similarly, for "B_id" = 21 the possessed "A_id" at present are as follows:
---------------------------
| A_id | Date(YYYY-MM-DD) |
---------------------------
| 10 | 2015-01-31 |
| 12 | 2014-01-11 |
I would highly appreciate your kind help in this regard.
One way to accomplish this is to use a correlated not exists predicate that makes sure that there doesn't exists any later possession for each A_ID with another B_ID.
SELECT A_ID, MAX(PDATE) AS DATE
FROM YOUR_TABLE T
WHERE B_ID = 6
AND NOT EXISTS (
SELECT 1
FROM YOUR_TABLE
WHERE A_ID = T.A_ID
AND PDATE > T.PDATE
AND B_ID <> T.B_ID
)
GROUP BY A_ID

Mysql Show records where timestamp interval is lower then 4 minutes

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