【问题标题】:Return rows that have one value but not another返回具有一个值但没有另一个值的行
【发布时间】:2017-09-08 20:14:13
【问题描述】:

对于每个相同的日期(这只是表格的一部分),我想返回购买 A 但没有购买 B 的帐号,反之亦然的另一个查询。因此,对 A 但没有 B 运行第一个查询应该返回 2 和 5。对 B 但没有 A 运行反之亦然查询应该给我 4。感谢您的帮助。我假设我必须在桌子上进行某种连接,但我被卡住了。

+----+----------------+---------------+----------+--+--+
| ID | Account Number | Purchase Type |   Date   |  |  |
+----+----------------+---------------+----------+--+--+
|  1 |              1 | A             | 20140301 |  |  |
|  1 |              1 | A             | 20140301 |  |  |
|  1 |              1 | B             | 20140301 |  |  |
|  2 |              2 | A             | 20140301 |  |  |
|  3 |              3 | A             | 20140301 |  |  |
|  3 |              3 | B             | 20140301 |  |  |
|  4 |              4 | B             | 20140301 |  |  |
|  5 |              5 | A             | 20140301 |  |  |
|  5 |              5 | A             | 20140301 |  |  |
+----+----------------+---------------+----------+--+--+

【问题讨论】:

  • 这是一个小提琴。 sqlfiddle.com/#!9/52c893/1/0
  • 返回ID/帐号同时拥有两者的查询是什么?
  • 我们能看到预期的结果吗?我不确定您是想要 2,4,5 在一个结果集中还是 2,5 然后 4 在两个单独的查询中。

标签: mysql


【解决方案1】:

不确定它是否一定是最好的方法,但内部 select 会起作用:

select distinct account_number
from purchases p
where purchase_type = "A" and account_number not in
(
  select account_number
  from purchases
  where purchase_date = p.purchase_date and purchase_type = "B"
)

您首先收集所有购买类型为“B”的 id,然后收集所有购买类型为“A”但不在第一个收集中的 id。

(假设您的表是 purchasesIDid intPurchase Datepurchase_date char(1)Datepurchase_date char(8),但您应该能够使查询适应您的实际列。

对应的小提琴:http://sqlfiddle.com/#!9/edf73f/7/0)

【讨论】:

    【解决方案2】:

    一种方法是使用完全外连接,其中一侧或另一侧为空;但 mySQL 不支持它们。所以模拟:使用左连接,然后使用联合(或联合全部,如果你想保持 1,1,A 存在两次的事实。)我们只需将连接之间的条件切换为第二个 SQL 到联合来处理两种方式。

    在评论中使用 SQL fiddle 的 DEMO:http://sqlfiddle.com/#!9/52c893/20/0

    SELECT A.*
    FROM purch A
    LEFT JOIN purch B
      on A.`Account Number` = B.`Account Number`
      AND B.`Purchase Type`  = 'B'
     WHERE b.`Account Number` is null
       AND A.`Purchase Type`  = 'A'
    
    UNION ALL
    
    SELECT A.*
    FROM purch A
    LEFT JOIN purch B
      on A.`Account Number` = B.`Account Number`
    
      AND B.`Purchase Type`  = 'A'
     WHERE b.`Account Number` is null
       AND A.`Purchase Type`  = 'B'
    

    【讨论】:

      【解决方案3】:

      您可以在同一张桌子上使用Exists

      select distinct AccountNumber , Date
      from table1 outer_table 
      where PurchaseType = 'A' and not exists
        (
          select ID 
          from table1 inner_table 
          where
             PurchaseType = 'B' 
             and inner_table.Date = outer_table.Date 
             and inner_table.AccountNumber = outer_table.AccountNumber
         )
      

      小提琴:http://sqlfiddle.com/#!9/b84ecd/9

      【讨论】:

      • 问题变成了他们想同时保留 5,5, A 的结果应该是 3 还是 4 条记录?
      • 好点。我将根据 OP 中所述的问题更新为不同的帐号/日期
      【解决方案4】:
      select id,sum(if(purchase_type='A',1,0)) as sumA,sum(if(purchase_type='B',1,0)) as sumB
      
      from purchases
      
      group by id
      
      having sumA>0 and sumB=0
      

      小提琴:http://sqlfiddle.com/#!9/edf73f/16

      将两个请求合二为一:

      select id,sum(if(purchase_type='A',1,0)) as sumA,sum(if(purchase_type='B',1,0)) as sumB 
      from purchases
      group by id
      having (sumA>0 and sumB=0) OR(sumA=0 and sumB>0 )
      

      小提琴:http://sqlfiddle.com/#!9/edf73f/18

      【讨论】:

        【解决方案5】:

        这里你有点搞砸了,因为 MySQL 的集合算术运算不完整。它有UNIONINTERSECT,但没有EXCEPT。如果它有EXCEPT 你可以这样做

        SELECT DISTINCT `Account Number` FROM purch WHERE `Purchase Type` = 'A' 
        EXCEPT    /* MySQL fail! */
        SELECT DISTINCT `Account Number` FROM purch WHERE `Purchase Type` = 'B' 
        

        你的问题就解决了。

        因此您可以使用LEFT JOIN ... IS NULL 查询模式。它更冗长但工作正常。 (http://sqlfiddle.com/#!9/52c893/18/0)

        SELECT  suba.`Account Number`
        
         FROM (
                  SELECT DISTINCT `Account Number`
                    FROM purch
                   WHERE `Purchase Type` = 'A'
               ) suba
          LEFT JOIN (
                  SELECT DISTINCT `Account Number`
                    FROM purch
                   WHERE `Purchase Type` = 'B'
               ) subb ON suba.`Account Number` =  subb.`Account Number`
         WHERE subb.`Account Number` IS NULL
        

        【讨论】:

          【解决方案6】:
          SELECT GROUP_CONCAT( DISTINCT   A.account SEPARATOR ', ') AS "accounts"
          FROM test A, test B
          WHERE A.type='A'
          AND A.id=B.id
          AND A.date=B.date
          AND A.date='2014-03-01'
          

          【讨论】:

          • 结果应该只有账户 2,4,5
          • 检查新请求:)
          • 为什么要得到 2,4,5 ? 5 是 A,4 是 B,你不能在查询中得到相同的结果,这就是你在你的问题中描述的,我错过了 smtg 吗?,如果我明白了,你必须有 1、2、3、5 和这就是我的查询得到的结果
          • "对 A 运行第一个查询但没有 B 应该返回 2 和 5。对 B 运行反之亦然查询但没有 A 应该给我 4。"但我们不知道这两个结果是否会同时出现。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-02
          相关资源
          最近更新 更多