2012-11-26 47 views
7

Tôi có một bảng mysql với 7 cột, trên đó mỗi hàng chứa các giá trị số nguyên.PHP MySQL cho hoán vị trên Bảng MySQL

Tôi có một trang web đơn giản nhận giá trị từ người dùng và tôi phải cố gắng xem liệu các giá trị được gửi bởi người dùng có trùng khớp hay tương tự với bất kỳ hàng nào trong bảng.

Vì vậy, người dùng viết ví dụ: 1 2 3 4 5 6 7 làm đầu vào.

Tôi phải tìm hiểu xem có bất kỳ hàng nào trong bảng của tôi tương tự như không có thứ tự. Vì vậy, 1 2 3 4 5 6 7 = 7 6 5 4 3 2 1 và cứ tiếp tục như vậy. Bảng của tôi chứa hơn 40.000 hàng dữ liệu.

Tôi cũng phải xem liệu họ có chia sẻ ít nhất 5, 6 hoặc 7 chữ số chung.

Điều này có nghĩa là sử dụng hoán vị để tìm tất cả các kết hợp có thể. Tuy nhiên cách tiếp cận tốt nhất cho một vấn đề như vậy là gì?

  1. Lấy đầu vào từ người dùng và nhận tất cả hoán vị và khớp với hàng đầu tiên, hàng thứ hai, v.v ... nếu có? Ngoài ra, làm ngược lại, nhận được một hàng từ bảng và nhận được tất cả hoán vị và làm các trận đấu chống lại đầu vào của người dùng?

  2. Điều gì về bộ nhớ và CPU khi đi qua một bảng lớn với nhiều hoán vị?

Cảm ơn mọi lời khuyên về điều này! Souciance

+0

Cách tiếp cận tốt nhất là sắp xếp dữ liệu nhập của người dùng và dữ liệu theo cùng thứ tự tăng dần và sau đó so sánh. –

Trả lời

1

phương pháp ánh sáng có thể là thêm trường bổ sung trong cơ sở dữ liệu của bạn, đây là phiên bản được sắp xếp theo số lượng của tất cả 7 trường được kết hợp.

ví dụ: nếu dữ liệu trong cơ sở dữ liệu là 2 4 7 6 5 1 3, trường kết hợp sẽ là 1234567

Sau đó, khi so sánh, hãy sắp xếp phản hồi của người dùng theo số và so sánh với trường kết hợp trong cơ sở dữ liệu.

Tùy thuộc vào những gì bạn đang làm, bạn có thể viết câu hỏi của bạn như thế này

select * from table where combination like '12%' or combination like '123%' 

Nếu bạn biết những gì số lượng tối thiểu các số phù hợp cần phải được, điều đó sẽ làm sáng lên các truy vấn

Để tìm hiểu tương tự những gì họ đã viết so với những gì có trong cơ sở dữ liệu. Bạn có thể sử dụng chức năng Levenshtein PHP: http://php.net/manual/en/function.levenshtein.php

$result = levenshtein($input,$combination); 
+0

Tôi thích ý tưởng này, có vẻ như là một cách tiếp cận tốt! –

0

Tôi sợ bạn không thể xây dựng truy vấn về vấn đề như thế này thực sự hiệu quả.

Bạn có thể xây dựng WHERE khoản như:

(`1` IN ARRAY(1,2,3,4,5,6,7) 
    AND `2` IN ARRAY(1,2,3,4,5,6,7) 
    AND `3` IN ARRAY(1,2,3,4,5,6,7) 
    AND `4` IN ARRAY(1,2,3,4,5,6,7) 
    AND `5` IN ARRAY(1,2,3,4,5,6,7)) 
OR 
(`1` IN ARRAY(1,2,3,4,5,6,7) 
    AND `2` IN ARRAY(1,2,3,4,5,6,7) 
    AND `3` IN ARRAY(1,2,3,4,5,6,7) 
    AND `4` IN ARRAY(1,2,3,4,5,6,7) 
    AND `6` IN ARRAY(1,2,3,4,5,6,7)) 
-- Each combination 

Nhưng đó sẽ là địa ngục của một điều kiện.Mặt khác bạn có thể thử sử dụng sự kết hợp của:

Trước séc nếu cột 1 chứa thông tin:

IF(`1` IN ARRAY(1,2,3,4,5,6,7), 1, 0) 

Sau đó tổng hợp tất cả các dữ liệu đó:

SELECT (
    IF(`1` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`2` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`3` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`4` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`5` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`6` IN ARRAY(1,2,3,4,5,6,7), 1, 0) + 
    IF(`7` IN ARRAY(1,2,3,4,5,6,7), 1, 0) 
) AS `matches_cnt` 
FROM t1 
HAVING `matches_cnt` >= 5 

Điều này sẽ lặp lại tất cả các hàng và điều kiện khá phức tạp (do đó hiệu suất của giường).

Bạn cũng có thể thử thay thế các giá trị của chuỗi nhị phân, ví dụ:

1,2,7 = 01000011 

Và sau đó tính toán Hamming distance giữa kỷ lục kiểm tra và cơ sở dữ liệu, nhưng điều này sẽ chỉ làm giảm độ phức tạp của điều kiện, nhưng cần phải lặp máng tất cả hồ sơ Sẽ vẫn như cũ.

thực hiện trong mysql sử dụng:

sẽ thay thế phần đầu tiên theo:

SELECT (
    $MAX_NUMBER$ - BIT_COUNT(XOR(`binary_representation`, $DATA_FROM_USER$)) 
) AS `matches_cnt` 
3

Trong một sơ đồ bình thường hóa đầy đủ này là một đĩa đơn có truy vấn

Giả sử bảng của bạn với pk như:

create table T1 
(pk char (1), a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int); 

insert into T1 values 
('a',1,2,3,4,5,6,7), 
('b',2,3,4,5,6,7,8), 
('z',10,11,12,13,14,15,16); 

Tại thời điểm này, chúng ta có thể chuẩn hóa dữ liệu như:

select 
    pk, 
    case a 
    when 1 then a1 
    when 2 then a2 
    when 3 then a3 
    when 4 then a4 
    when 5 then a5 
    when 6 then a6 
    when 7 then a7 
    end 
    as v 
from T1 
cross join 
    (select 1 as a from dual union all 
    select 2 as a from dual union all 
    select 3 as a from dual union all 
    select 4 as a from dual union all 
    select 5 as a from dual union all 
    select 6 as a from dual union all 
    select 7 as a from dual) T2 

Trong truy vấn trước đó, nó rất dễ dàng để phù hợp với yêu cầu của bạn với một đơn có:

select pk 
from 
(
select 
    pk, 
    case a 
    when 1 then a1 
    when 2 then a2 
    when 3 then a3 
    when 4 then a4 
    when 5 then a5 
    when 6 then a6 
    when 7 then a7 
    end 
    as v 
from T1 
cross join 
    (select 1 as a from dual union all 
    select 2 as a from dual union all 
    select 3 as a from dual union all 
    select 4 as a from dual union all 
    select 5 as a from dual union all 
    select 6 as a from dual union all 
    select 7 as a from dual) T2 
) T 
where 
    T.v in (4,5,6,7,8,9,10) 
group by pk 
having           <-- The Having 
    count(pk) > 4 

Results:

| PK | 
------ 
| b | 
+0

Hmmm..đã không thấy cách tiếp cận có, cảm ơn vì giải pháp, chắc chắn sẽ cung cấp cho nó một đi! –