2011-02-17 11 views
8

Tôi muốn tìm kiếm bản ghi trong đó một trường cụ thể BẮT ĐẦU VỚI một số chuỗi (giả sử "ar") HOẶC trường đó CONTAINS chuỗi, "ar".Điều kiện trọng số trong mệnh đề WHERE của câu lệnh SQL

Tuy nhiên, tôi xem xét hai điều kiện khác nhau, vì tôi đang giới hạn số lượng kết quả được trả về 10 và tôi muốn điều kiện STARTS WITH được cân nặng hơn nhiều so với điều kiện CONTAINS.

Ví dụ:

SELECT * 
FROM Employees 
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%' 
LIMIT 10 

Việc nắm bắt được đó là nếu có tên bắt đầu bằng "ar" họ nên được ưa chuộng. Cách duy nhất tôi nên lấy lại tên chỉ chứa "ar" là nếu có ít hơn 10 tên BẮT ĐẦU với "ar"

Làm cách nào tôi có thể thực hiện việc này đối với cơ sở dữ liệu MySQL?

Trả lời

10

Bạn cần chọn chúng trong 2 phần và thêm thẻ Tùy chọn vào kết quả. 10 từ mỗi đoạn, sau đó kết hợp chúng và mất một lần nữa là tốt nhất 10. Nếu phân đoạn 1 sản xuất 8 mục, sau đó phân khúc 2 của UNION ALL sản phẩm sẽ còn lại 2

SELECT * 
FROM 
(
SELECT *, 1 as Preferred 
FROM Employees 
WHERE Name LIKE 'ar%' 
LIMIT 10 
UNION ALL 
SELECT * 
FROM 
(
    SELECT *, 2 
    FROM Employees 
    WHERE Name NOT LIKE 'ar%' AND Name LIKE '%ar%' 
    LIMIT 10 
) X 
) Y 
ORDER BY Preferred 
LIMIT 10 
+0

+1. Đồng ý, điều này hiệu quả hơn. – mellamokb

+0

Điều này dường như làm việc cho tôi. Bạn có thể giải thích nó không?Tôi hiểu (nói chung) nghĩa là gì. X và Y là gì, 1 và 2 là gì? –

+1

@Stephen - X và Y chỉ là bí danh cho các truy vấn con (mỗi bảng dẫn xuất phải được đặt bí danh - để chúng có thể được tham chiếu nếu được yêu cầu). Bạn có thể thêm một cột vào bất kỳ tập kết quả nào, bằng cách chỉ đưa ra một giá trị và đặt tên (đánh dấu) cột. Trong trường hợp này, tôi đã thêm một cột có tên "Ưu tiên" với giá trị là 1 trong phần đầu tiên và giá trị là 2 trong phần thứ hai. Các cột bây giờ là một phần của kết quả (cho truy vấn). – RichardTheKiwi

4

Gán một giá trị mã để kết quả, và sắp xếp theo giá trị mã:

select 
    *, 
    (case when name like 'ar%' then 1 else 2 end) as priority 
from 
    employees 
where 
    name like 'ar%' or name like '%ar%' 
order by 
    priority 
limit 10 

Edit:

Xem Richard aka câu trả lời cyberkiwi cho một giải pháp hiệu quả hơn nếu có rất nhiều trận đấu có khả năng .

+0

Nếu bảng chứa nhiều các trận đấu , thì điều này có thể chậm hơn vì trước tiên nó phải chỉ định mức độ ưu tiên cho tất cả các kết quả phù hợp. – RichardTheKiwi

0

Hãy thử điều này (không có một trường hợp MySQL có sẵn ngay lập tức để kiểm tra với):

SELECT * FROM 
    (SELECT * FROM Employees WHERE Name LIKE 'ar%' 
    UNION 
    SELECT * FROM Employees WHERE Name LIKE '%ar%' 
    ) 
LIMIT 10 

Có nhiều cách có lẽ tốt hơn để làm điều đó, nhưng điều đó ngay lập tức mọc trong tâm trí.

0

giải pháp của tôi là:

SELECT * 
FROM Employees 
WHERE Name LIKE '%ar%' 
ORDER BY instr(name, 'ar'), name 
LIMIT 10 

instr() tìm kiếm sự xuất hiện đầu tiên của mẫu được đề cập. AR% sẽ đến trước xxAR.

Điều này ngăn cản:

  1. chỉ nên làm bảng quét 1 lần. Các đoàn thể và bảng dẫn xuất làm 3. Hai đầu tiên trên các cột để lọc ra các mẫu và sau đó là số thứ ba trên tập hợp con để tìm vị trí chúng bằng nhau - vì công đoàn lọc ra các số hai.

  2. Cung cấp loại thực sự dựa trên vị trí của mẫu. Wx> XW> xxW> vv ...

0
SELECT * 
FROM Employees 
WHERE Name LIKE 'ar%' OR Name LIKE '%ar%' 
ORDER BY LIKE 'ar%' DESC 
LIMIT 10 

nên làm việc đơn đặt hàng của các nhị phân đúng/sai cho thích và nếu index'ed nên được hưởng lợi từ các chỉ số