【问题标题】:MySQL - Select everything from one table, but only first matching value in second tableMySQL - 从一个表中选择所有内容,但仅在第二个表中选择第一个匹配值
【发布时间】:2023-03-24 10:56:01
【问题描述】:

我对在 MySQL 中创建查询感到有些生疏。我以为我可以解决这个问题,但我没有运气,四处搜索也不会产生类似的结果......

基本上,我有两张桌子。我想从一个表中选择所有内容,并从第二个表中选择匹配的行。但是,我只想从第二个表中获得第一个结果。我希望这是有道理的。

daily_entries 表中的行是唯一的。每天会有一排,但可能不是每天。第二个表notes 包含许多行,每一行都与daily_entries 中的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    |                |
+----------+--------------+------+-----+---------+----------------+

表二

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    |                |
+---------+---------+------+-----+---------+----------------+

我需要做的是从notes 中选择所有条目,从daily_entries 中只有一个结果。

下面是我希望它的外观示例:

+----------------------------------------------+---------+------------+----------+-----+
| 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)

以下是我目前的查询:

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

以下是我的查询的外观示例:

+----------------------------------------------+---------+------------+----------+-----+
| 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)

起初我以为我可以简单地GROUP BY daily_entries.date,但它只返回每个匹配集的第一行。这甚至可以做到吗?我将非常感谢有人可以提供的任何帮助。在我的查询末尾使用 Limit 显然将其限制为我指定的值,但将其应用于预期的所有内容。

【问题讨论】:

  • 通常这些类型的格式改进是在应用程序级别完成的(例如,报告工具有一个“抑制重复值”选项)
  • 您能否确认您想要第二个表中的最新行(如果存在)?

标签: mysql sql select


【解决方案1】:

基本上,您的查询没有任何问题。我相信这正是您所需要的,因为它正在返回您想要的数据。您不能将其视为复制您的daily_entries,您应该将其视为返回所有notes 及其关联的daily_entry

当然,您可以实现您在问题中描述的内容(已经有解决此问题的答案),但在执行此操作之前请三思而后行,因为此类嵌套查询只会给您的数据库服务器增加很多明显的性能开销。

我建议使用一个 LEFT JOIN(这就是您所需要的全部)使您的查询尽可能简单,然后让消费应用程序处理数据并以他们需要的方式呈现它。

【讨论】:

  • 谢谢。我接受了您的建议,并按照当前编写的方式保留了查询。该数据被馈送到动态网页,因此我只是在 cgi 脚本的表中删除了该列中的重复数据。不知道为什么我一开始不这样做,因为这是一个两分钟的修复。其他两个答案似乎也返回了所有数据,就像我原来的查询一样??
【解决方案2】:

使用mysql的非标准分组功能:

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

【讨论】:

    【解决方案3】:

    您需要对最后一行进行显式过滤来执行这些查询。此示例使用join 来执行此操作:

    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;
    

    【讨论】:

      猜你喜欢
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多