2014-07-25 86 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的執行計劃通常沒有那麼重要,因爲沒有索引,數據規模太小 - 但兩種方法沒有太大差別。 –