简体   繁体   中英

MySQL - Select everything from one table, but only first matching value in second table

I'm feeling a little rusty with creating queries in MySQL. I thought I could solve this, but I'm having no luck and searching around doesn't result in anything similar...

Basically, I have two tables. I want to select everything from one table and the matching row from the second table. However, I only want to have the first result from the second table. I hope that makes sense.

The rows in the daily_entries table are unique. There will be one row for each day, but maybe not everyday. The second table notes contains many rows, each of which are associated with ONE row from daily_entries .

Below are examples of my tables;

Table One

mysql> desc daily_entries;

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| eid      | int(11)      | NO   | PRI | NULL    | auto_increment |
| date     | date         | NO   |     | NULL    |                |
| location | varchar(100) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

Table Two

mysql> desc notes;
+---------+---------+------+-----+---------+----------------+
| Field   | Type    | Null | Key | Default | Extra          |
+---------+---------+------+-----+---------+----------------+
| task_id | int(11) | NO   | PRI | NULL    | auto_increment |
| eid     | int(11) | NO   | MUL | NULL    |                |
| notes   | text    | YES  |     | NULL    |                |
+---------+---------+------+-----+---------+----------------+

What I need to do, is select all entries from notes , with only one result from daily_entries .

Below is an example of how I want it to look:

+----------------------------------------------+---------+------------+----------+-----+
| notes                                        | task_id | date       | location | eid |
+----------------------------------------------+---------+------------+----------+-----+
| Another note                                 |       3 | 2014-01-02 | Home     |   2 |
| Enter a note.                                |       1 | 2014-01-01 | Away     |   1 |
| This is a test note. To see what happens.    |       2 |            | Away     |   1 |
| Testing another note                         |       4 |            | Away     |   1 |
+----------------------------------------------+---------+------------+----------+-----+
4 rows in set (0.00 sec)

Below is the query that I currently have:

SELECT notes.notes, notes.task_id, daily_entries.date, daily_entries.location, daily_entries.eid
FROM daily_entries
LEFT JOIN notes ON daily_entries.eid=notes.eid
ORDER BY daily_entries.date DESC

Below is an example of how it looks with my query:

+----------------------------------------------+---------+------------+----------+-----+
| notes                                        | task_id | date       | location | eid |
+----------------------------------------------+---------+------------+----------+-----+
| Another note                                 |       3 | 2014-01-02 | Home     |   2 |
| Enter a note.                                |       1 | 2014-01-01 | Away     |   1 |
| This is a test note. To see what happens.    |       2 | 2014-01-01 | Away     |   1 |
| Testing another note                         |       4 | 2014-01-01 | Away     |   1 |
+----------------------------------------------+---------+------------+----------+-----+
4 rows in set (0.00 sec)

At first I thought I could simply GROUP BY daily_entries.date , however that returned only the first row of each matching set. Can this even be done? I would greatly appreciate any help someone can offer. Using Limit at the end of my query obviously limited it to the value that I specified, but applied it to everything which was to be expected.

Basically, there's nothing wrong with your query. I believe it is exactly what you need because it is returning the data you want. You can not look at as if it is duplicating your daily_entries you should be looking at it as if it is return all notes with its associated daily_entry .

Of course, you can achieve what you described in your question (there's an answer already that solve this issue) but think twice before you do it because such nested queries will only add a lot of noticeable performance overhead to your database server.

I'd recommend to keep your query as simple as possible with one single LEFT JOIN (which is all you need) and then let consuming applications manipulate the data and present it the way they need to.

Use mysql's non-standard group by functionality:

SELECT n.notes, n.task_id, de.date, de.location, de.eid
FROM notes n
LEFT JOIN (select * from 
  (select * from daily_entries ORDER BY date DESC) x 
  group by eid) de ON de.eid = n.eid

You need to do these queries with explicit filtering for the last row. This example uses a join to do this:

SELECT n.notes, n.task_id, de.date, de.location, de.eid
FROM daily_entries de LEFT JOIN
     notes n
     ON de.eid = n.eid LEFT JOIN
     (select n.eid, min(task_id) as min_task_id
      from notes n
      group by n.eid
     ) nmin
     on n.task_id = nmin.min_task_id
ORDER BY de.date DESC;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM