AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 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

Como selecionar apenas membros que não fizeram nenhum depósito este mês no mysql

  • 772

Estou buscando dados de duas tabelas, membros e taxas. Gostaria de selecionar apenas os membros que não fizeram nenhum depósito este mês. Isto é o que eu tentei, mas os resultados não são o que eu pretendo obter. Qualquer ajuda será apreciada . Estou usando 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 respostas
  • 979 Views

2 respostas

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

    Você precisa fazer isso de uma maneira diferente: escolha todos os membros que não são INo conjunto de membros que pagaram algo este mês :

    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 aqui

    Você realmente consulta membros especificados que pagaram algo nos anos anteriores ao atual e no mês anterior ao atual.


    Como segunda alternativa, você pode usar 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 aqui


    E ainda outra alternativa (não tão clara, na minha opinião), faça a LEFT JOINe defina uma WHEREcondição que filtrará as linhas realmente recuperando algo do lado direito do JOIN (ou seja: usando apenas as linhas WHEREtodas as colunas, e especificamente memberidsão NULL do lado direito):

    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 */
    

    Verifique as melhores práticas entre usar LEFT JOIN ou NOT EXISTS

    E verifique todos os dbfiddle aqui

    Isso é chamado, em álgebra relacional, uma antijunção

    ATUALIZAR

    Dando um passo além da solução do Kondybas , e como apontado nos comentários à resposta do Kondibas por ypercube , isso pode ser simplificado ainda mais para:

    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 ;
    

    Escrevendo a condição assim (ou seja: não ter uma função aplicada a paiddate), ele usará um índice como:

    CREATE INDEX idx_member_date ON fees (memberid, paiddate);
    

    ... como pode ser visto no plano de execução:

    identificação | select_type | mesa | tipo | chaves_possíveis | chave | key_len | ref | linhas | Extra                   
    -: | :---------- | :------ | :--- | :-------------- | :-------------- | :------ | :------------------------------------------- | ---: | :-----------------------
     1 | SIMPLES | membros | TODOS | nulo             | nulo             | nulo     | nulo                                          | 2 |                         
     1 | SIMPLES | taxas | ref | idx_member_date | idx_member_date | 5 | fiddle_ZCXLEXEURTHEWEPFKPOV.members.memberid | 1 | Usando onde; Usando o índice
    

    dbfiddle aqui

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

    A terceira alternativa para as soluções do joanolo é buscar registros com NULLs LEFT JOINde tabelas:

    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
    ;
    

    Como sugerido pelo yupecube , a consulta pode ser simplificada para:

    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
    ;
    

    A única desvantagem é que os JOINs em condições funcionais complexas são, em geral, muito lentos.

    • 3

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve