2014-07-25 12 views
7

Tôi đang cố gắng chọn bản ghi trùng lặp dựa trên một kết hợp của ba cột. Danh sách các bộ ba có thể rất dài (1000), vì vậy tôi muốn làm cho nó ngắn gọn.MySql IN mệnh đề, cố gắng để phù hợp với IN danh sách các bộ dữ liệu

Khi tôi có một danh sách các kích thước 10 (được gọi bản sao) nó chỉ phù hợp 2 (những người dường như ngẫu nhiên) và bỏ lỡ khác 8. Tôi dự kiến ​​10 hồ sơ để trở lại, nhưng chỉ thấy 2.

Tôi đã thu hẹp nó xuống vấn đề này:

Điều này trả về một bản ghi. Mong 2:

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

Trả hai kỷ lục, như mong đợi:

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)) 

Bất cứ ý tưởng tại sao truy vấn đầu tiên chỉ trả lại một bản ghi?

+2

tôi đã không thể tái tạo các vấn đề trên máy tính của tôi (MySQL 5.6 .14). Bạn có thể làm cho một fiddle? – Vatev

+0

Bạn có thể chỉnh sửa câu hỏi của mình và mô tả các loại cột dữ liệu ('SHOW CREATE TABLE ali') không? Nếu bạn đang sử dụng 'FLOAT' hoặc' DOUBLE' cho cột 'x', nó có thể gây ra sự so sánh bình đẳng thất bại vì giá trị chính xác được làm tròn theo cách không mong muốn. Ngoài ra, vui lòng chỉ định chính xác phiên bản MySQL nào bạn sử dụng. –

+0

Bạn có thể đăng mã bạn đang sử dụng không. Tôi đã sao chép nó vào một cái bàn và lúc đầu nó trông giống như một giá trị toán hạng, nhưng đó là lỗi của tôi khi thiếu một bộ ngoặc đơn. Giống như Vatev tôi đã không thể tái sản xuất vấn đề – DanceSC

Trả lời

1

tôi muốn đề nghị bạn không sử dụng IN() cho điều này, thay vì sử dụng một truy vấn mà tồn tại, ví dụ:

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 
      ) 
; 

tôi đã có thể sinh sản một vấn đề (so sánh http://sqlfiddle.com/#!2/7d2658/6-http://sqlfiddle.com/#!2/fe851/1 cả MySQL 5,5 .3) trong trường hợp nếu cột x là số và giá trị âm, nó không khớp với hàm IN() nhưng được kết hợp khi số hoặc chữ số thập phân sử dụng bảng và vị trí tồn tại.

Có lẽ không phải là một bài kiểm tra kết luận nhưng cá nhân tôi sẽ không sử dụng IN() cho điều này.

Tại sao bạn không xác định các bản sao theo cách này?

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

Sau đó, sử dụng như một bảng có nguồn gốc trong nơi có điều kiện:

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 
      ) 

thấy http://sqlfiddle.com/#!2/ede292/1 cho truy vấn ngay trên

+0

[Cú pháp nối bên trong dường như đơn giản hơn] (http://sqlfiddle.com/#!2/ede292/2) với tôi. Tôi cũng mong đợi sự tham gia có hiệu quả, mặc dù, theo SQL Fiddle, các kế hoạch truy vấn khác nhau và tôi không giỏi giải thích chúng. –

+0

có, điểm tốt, tham gia bên trong bằng cách sử dụng cùng một bảng có nguồn gốc là một lựa chọn quá. Các kế hoạch thực hiện của sqlfiddle thường không có liên quan vì không có chỉ mục và quy mô dữ liệu quá nhỏ - nhưng không có sự khác biệt lớn trong 2 phương pháp tiếp cận. –

Các vấn đề liên quan