【问题标题】:In MySQL get the User who is not Reserved for Last Month在 MySQL 中获取未保留上个月的用户
【发布时间】:2013-08-28 17:59:07
【问题描述】:

我正在使用MySQL 数据库,我有两个表。他们是UserReservation

这是我的问题。

  1. 目前,我使用LEFT JOINNOT EXIST 的SubQuery 怎么样。从性能的角度来看,哪个更好?
  2. 我可以为此查询创建视图吗,这会对性能产生任何影响

用户

| FIELD |        TYPE | NULL | KEY | DEFAULT |          EXTRA |
|-------|-------------|------|-----|---------|----------------|
|   uid |     int(11) |   NO | PRI |  (null) | auto_increment |
| uname | varchar(30) |  YES |     |  (null) |                |

预订

|    FIELD |      TYPE | NULL | KEY |           DEFAULT |          EXTRA |
|----------|-----------|------|-----|-------------------|----------------|
|      rid |   int(11) |   NO | PRI |            (null) | auto_increment |
|      uid |   int(11) |  YES | MUL |            (null) |                |
| reserved | timestamp |   NO |     | CURRENT_TIMESTAMP |                |

SQL 代码:

create table user (
 uid int not null auto_increment,
 uname varchar(30),
 primary key(uid)
);

create table reservation (
 rid int not null auto_increment,
 uid int,
 reserved timestamp not null default CURRENT_TIMESTAMP,
 primary key(rid),
 foreign key (uid) references user (uid)
)

我当前工作的 SQL 查询

SELECT u.uid, u.uname, date_format(reserved, '%Y%m')  
FROM user as u 
LEFT JOIN reservation as r on  
r.uid = u.uid and date_format(reserved, '%Y%m') = 201307  
where r.uid is null  

【问题讨论】:

标签: mysql select


【解决方案1】:

这是一篇关于性能差异的优秀文章:NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: MySQL

总结:

...在 MySQL 中搜索缺失值的最佳方法是使用 LEFT JOIN / IS NULL 或 NOT IN 而不是 NOT EXISTS。

但是您可以通过在保留列上放置索引并像这样重写查询来稍微提高性能:

reserved >= '2013-07-01 00:00:00' AND reserved < '2013-08-01 00:00:00'

视图不会改变查询的任何性能。

【讨论】:

    【解决方案2】:

    问题是,如果您执行date_format,则不会使用 MySQL 索引。你应该使用这样的东西:

    reserved >= '2013-07-01 00:00:00' AND reserved < '2013-08-01 00:00:00'
    

    比使用索引,您的查询会更快。如果您在表预订上有一个组合索引,带有字段,uid, reserved

    【讨论】:

      【解决方案3】:

      不存在会更好。

      SELECT u.uid, u.uname, date_format(reserved, '%Y%m')  
      FROM user as u where not exist (select 1 from reservation as r   
      where r.uid = u.uid and date_format(reserved, '%Y%m') = 201307)
      

      视图对性能没有多大帮助。它主要关注可重用性、数据隐藏和安全原因。

      【讨论】:

      • 这不回答 OP 的问题(即什么更好以及为什么)
      • 我已指定“不存在”在这种情况下比左连接执行得更好。并回答为什么,不存在(半连接)只是检查子查询中的数据是否存在。左连接必须连接两个表,后跟过滤谓词
      • Left Join 比 Sub 查询好!检查此链接:stackoverflow.com/questions/2577174/join-vs-subquery
      • 并非总是如此,试着理解这里的场景,他试图在左连接的帮助下做(A 减 b)。不要盲目地使用连接与子查询。这取决于我们所处的场景以及我们想要什么。
      【解决方案4】:

      您会想要使用NOT EXISTS,并且创建视图不会对您有太大帮助,即使是为了方便,因为这是一个非常简单的查询。

      另见:SQL performance on LEFT OUTER JOIN vs NOT EXISTS

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-15
        • 1970-01-01
        • 1970-01-01
        • 2020-02-25
        • 1970-01-01
        • 2017-12-26
        • 2021-07-30
        • 2021-03-20
        相关资源
        最近更新 更多