AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 177172
Accepted
humphrey
humphrey
Asked: 2017-06-25 06:38:09 +0800 CST2017-06-25 06:38:09 +0800 CST 2017-06-25 06:38:09 +0800 CST

如何在mysql中只选择本月没有存款的会员

  • 772

我正在从成员和费用这两个表中获取数据。我想只选择那些本月没有存款的成员。这是我尝试过的,但结果不是我想要得到的。任何帮助将不胜感激 。我正在使用 mysql 。

SELECT
    members.memberid, 
    members.companyid, 
    members.name, 
    members.initials, 
    members.surname, 
    members.datejoined,
    members.usercode, 
    members.address, 
    members.cell, 
    members.pic, 
    members.idnumber, members.rank, 
    members.address2,
    fees.feestype,fees.amountpaid,
    fees.companyid,fees.paiddate,
    fees.usercode
FROM 
    members
    INNER JOIN fees
        ON members.memberid = fees.memberid
WHERE 
        MONTH(fees.paiddate) < MONTH(CURDATE())
    AND YEAR(fees.paiddate)  < YEAR(CURDATE())  
mysql
  • 2 2 个回答
  • 979 Views

2 个回答

  • Voted
  1. Best Answer
    joanolo
    2017-06-25T06:54:03+08:002017-06-25T06:54:03+08:00

    您需要以不同的方式进行:选择不是本月支付IN的成员集合的所有成员:

    SELECT
        memberid, name  /* , and anything you need */
    FROM
        members
        /* JOIN fees ON fees.memberid = members.memberid */
    WHERE
        memberid NOT IN
        (
        /* members who paid something this month */ 
        SELECT 
            memberid
        FROM
            fees
        WHERE
            YEAR(paiddate)  = YEAR(curdate())  AND
            MONTH(paiddate) = MONTH(curdate())
        ) ;
    

    dbfiddle在这里

    您实际查询在当前年份之前的年份和当前年份之前的月份支付过费用的特定成员。


    作为第二种选择,您可以使用NOT EXISTS:

    SELECT
        memberid, name  /* , and anything you need */
    FROM
        members
        /* JOIN fees ON fees.memberid = members.memberid */
    WHERE
        NOT EXISTS
        (
        /* any payment from this specific member this month */ 
        SELECT 
            1
        FROM
            fees
        WHERE
            fees.memberid = members.memberid   AND
            YEAR(paiddate)  = YEAR(curdate())  AND
            MONTH(paiddate) = MONTH(curdate())
        ) ;
    

    dbfiddle在这里


    还有另一个(我认为不太清楚)替代方案,执行LEFT JOIN并设置一个WHERE条件,该条件将过滤掉实际从 JOIN 右侧检索某些内容的行(即:仅使用所有列的行WHERE,特别memberid是 NULL在右侧):

    SELECT
        members.memberid, members.name  /* , and anything you need */
    FROM
        members
        /* JOIN fees ON fees.memberid = members.memberid */
        LEFT JOIN /* Imperative to be LEFT JOIN */
        (
        /* members who paid this month */ 
        SELECT 
            fees.memberid
        FROM
            fees
        WHERE
            YEAR(paiddate)  = YEAR(curdate())  AND
            MONTH(paiddate) = MONTH(curdate())
        ) AS s0 
        ON s0.memberid = members.memberid
    WHERE
        s0.memberid IS NULL /* The LEFT JOIN produced nothing on the right side */
    

    检查使用 LEFT JOIN 或 NOT EXISTS 之间的最佳实践

    并在此处检查所有dbfiddle

    在关系代数中,这称为反连接

    更新

    从Kondybas的解决方案更进一步,正如 ypercube 在对Kondibas回答的评论中所指出的,这可以进一步简化为:

    SELECT
        members.memberid, members.name  /* , and anything you need */
    FROM
        members
        /* JOIN fees f1 ON fees.memberid = members.memberid */
        LEFT JOIN fees f2 ON 
            f2.memberid = members.memberid AND
            f2.paiddate BETWEEN date_format(curdate() ,'%Y-%m-01') AND curdate()
    WHERE
        f2.memberid IS NULL ;
    

    像这样写条件(即:没有应用到 paiddate 的函数),它将使用一个索引,例如:

    CREATE INDEX idx_member_date ON fees (memberid, paiddate);
    

    ...从执行计划中可以看出:

    编号 | 选择类型 | 表 | 类型 | 可能的键 | 钥匙 | 密钥长度 | 参考 | 行 | 额外的                   
    -: | :------------ | :------ | :--- | :---------------- | :---------------- | :------ | :---------------------------------------- | ---: | :------------------------
     1 | 简单 | 成员 | 所有 | 空            | 空            | 空    | 空                                         | 2 |                         
     1 | 简单 | 费用 | 参考 | idx_member_date | idx_member_date | 5 | fiddle_ZCXLEXEURTHEWEPFKPOV.members.memberid | 1 | 在哪里使用;使用索引
    

    dbfiddle在这里

    • 4
  2. Kondybas
    2017-06-25T08:06:51+08:002017-06-25T08:06:51+08:00

    joanolo解决方案的第三种替代方法是从表中获取带有 NULL 的记录LEFT JOIN:

    SELECT w.id
      FROM members AS w
      LEFT JOIN fees AS z ON w.memberid = z.memberid
     WHERE DATE_FORMAT(z.paiddate, '%Y%M') = DATE_FORMAT(NOW(), '%Y%M')
        OR z.paiddate IS NULL
    HAVING z.paiddate IS NULL
    ;
    

    正如yupecube建议的那样,查询可以简化为:

    SELECT w.id
      FROM members AS w
      LEFT JOIN fees AS z
             ON w.memberid = z.memberid 
            AND DATE_FORMAT(z.paiddate, '%Y%M') = DATE_FORMAT(NOW(), '%Y%M')
     WHERE z.paiddate IS NULL
    ;
    

    唯一的缺点是复杂功能条件下的 JOIN 通常非常慢。

    • 3

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve