2014-07-25 29 views
7

我想根据三列匹配来选择重复记录。三元组列表可能会很长(1000),所以我想简要说明一下。MySql IN子句,试图匹配IN元组列表

当我有大小10(称为副本)的列表,它只匹配2(看似随机的),错过其他8.我预计10条记录返回,但只看到了2

我已经缩小到这个问题:

这将返回一条记录。期待二:

select * 
from ali 
where (accountOid, dt, x) in 
(
    (64, '2014-03-01', 10000.0), 
    (64, '2014-04-23', -122.91) 
) 

返回两个记录,符合市场预期:

select * 
from ali 
where (accountOid, dt, x) in ((64, '2014-03-01', 10000.0)) 
or (accountOid, dt, x) in ((64, '2014-04-23', -122.91)) 

任何想法,为什么第一个查询只返回一个记录?

+2

我无法重现我的机器上的问题(的MySQL 5.6 0.14)。你可以做小提琴吗? – Vatev

+0

你可以编辑你的问题并描述列的数据类型('SHOW CREATE TABLE ali')吗?如果对'x'列使用'FLOAT'或'DOUBLE',它可能导致等值比较失败,因为精确值会以意想不到的方式舍入。另请指明您使用的是哪个版本的MySQL。 –

+0

你可以发布你正在使用的代码吗?我将它复制到一张表中,起初它看起来像是一个操作数值,但这是我错误地忽略了一个括号集。像Vatev一样,我无法再现问题 – DanceSC

回答

1

我建议你不要使用IN()对于这一点,而不是使用其中存在的查询,如:

CREATE TABLE inlist 
    (`id` int, `accountOid` int, `dt` datetime, `x` decimal(18,4)) 
; 

INSERT INTO inlist 
    (`id`, `accountOid`, `dt`, `x`) 
VALUES 
    (1, 64, '2014-03-01 00:00:00', 10000.0), 
    (2, 64, '2014-04-23 00:00:00', -122.91) 
; 

select * 
from ali 
where exists (select null 
       from inlist 
       where ali.accountOid = inlist.accountOid 
       and ali.dt = inlist.dt 
       and ali.x = inlist.x 
      ) 
; 

我能够重现问题(比较http://sqlfiddle.com/#!2/7d2658/6http://sqlfiddle.com/#!2/fe851/1 MySQL的两个5.5 .3)如果x列是数字并且值是负值,那么它使用IN()不匹配,但在使用表的数字或十进制时以及在哪里存在时匹配。

也许不是一个确定的测试,但个人而言,我不会使用IN()。

你为什么不以这种方式确定重复?

select 
     accountOid 
     , dt 
     , x 
from ali 
group by 
     accountOid 
     , dt 
     , x 
having 
     count(*) > 1 

然后使用它作为其中内派生表存在条件:

select * 
from ali 
where exists (
       select null 
       from (
         select 
           accountOid 
          , dt 
          , x 
         from ali 
         group by 
           accountOid 
          , dt 
          , x 
         having 
           count(*) > 1 
        ) as inlist 
       where ali.accountOid = inlist.accountOid 
       and ali.dt = inlist.dt 
       and ali.x = inlist.x 
      ) 

看到http://sqlfiddle.com/#!2/ede292/1用于查询正上方

+0

[inner join语法看起来更简单]给我(http://sqlfiddle.com/#!2/ede292/2)。我也希望这个连接效率很高,但根据SQL Fiddle的说法,查询计划确实有所不同,我不擅长解释这些连接。 –

+0

是的,好点,使用同一个派生表的内部连接也是一个选项。 sqlfiddle的执行计划通常没有那么重要,因为没有索引,数据规模太小 - 但两种方法没有太大差别。 –