2010-06-20 30 views
11

Tôi đang cố gắng tìm số thấp nhất trong hai cột của một hàng trong cùng một bảng, với báo trước rằng một trong các cột có thể là null trong một hàng cụ thể. Nếu một trong các cột là null, tôi muốn giá trị trong cột khác được trả về cho hàng đó, vì đó là cột không null thấp nhất trong trường hợp này. Nếu tôi sử dụng hàm minimum() trong MySQL 5.1:Làm cách nào để tìm ít cột không rỗng nhất trong một hàng cụ thể trong SQL?

select least(1,null) 

Điều này trả về null, không phải là điều tôi muốn. Tôi cần truy vấn trả về 1 trong trường hợp này.

tôi đã có thể để có được những kết quả tôi muốn nói chung với truy vấn này:

select least(coalesce(col1, col2)) , coalesce(col2,col1)) 

Chừng nào col1 và col2 đều không null mỗi kết thành một khối tuyên bố sẽ trả về một số, và ít nhất () xử lý việc tìm kiếm thấp nhất.

Có cách nào đơn giản/nhanh hơn để thực hiện việc này không? Tôi đang sử dụng MySQL trong trường hợp này nhưng các giải pháp chung được hoan nghênh.

+1

nhanh hơn? Bạn đã xác định nó là chậm? –

+0

Chưa đánh giá nó là chậm nhất thiết, nhưng nó gọi 3 chức năng thay vì có thể một. Tôi đang sử dụng nó theo thứ tự theo mệnh đề của truy vấn tôi cần càng nhanh càng tốt. –

Trả lời

11

Thật không may (đối với trường hợp của bạn) hành vi của LEAST đã được thay đổi trong MySQL 5.0.13 (http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_least) - nó được sử dụng để trả về NULL chỉ khi tất cả các đối số là NULL.

Thay đổi này thậm chí còn được báo cáo là lỗi: http://bugs.mysql.com/bug.php?id=15610 Nhưng bản sửa lỗi chỉ dành cho tài liệu MySQL, giải thích hành vi mới và khả năng tương thích.

Giải pháp của bạn là một trong những cách giải quyết được đề xuất. Khác có thể được sử dụng NẾU điều hành:

SELECT IF(Col1 IS NULL OR Col2 IS NULL, COALESCE(Col1, Col2), LEAST(Col1,Col2)) 
3

Điều này có thể thực hiện tốt hơn một chút (có thể phải được chuyển đổi sang tương ứng MySql cú pháp):

SELECT 
    CASE 
    WHEN Col1 IS NULL THEN Col2 
    WHEN Col2 IS NULL THEN Col1 
    ELSE Least(Col1, Col2) 
    END 

Một lựa chọn khác (có thể là chậm hơn mặc dù, nhưng cũng đáng thử):

SELECT Col1 
WHERE Col2 IS NULL 
UNION 
SELECT Col2 
WHERE Col1 IS NULL 
UNION 
SELECT least(Col1, Col2) 
WHERE Col1 IS NOT NULL AND Col2 IS NOT NULL 
3

Tùy thuộc vào góc của trường hợp tình hình có tất cả các giá trị được null, tôi sẽ đi cho cú pháp như vậy, đó là dễ đọc hơn (Một giải pháp dễ dàng hơn nếu bạn có chính xác hai cột dưới !)

SELECT LEAST(IFNULL(5, ~0 >> 1), IFNULL(10, ~0 >> 1)) AS least_date; 
-- Returns: 5 

SELECT LEAST(IFNULL(null, ~0 >> 1), IFNULL(10, ~0 >> 1)) AS least_date; 
-- Returns: 10 

SELECT LEAST(IFNULL(5, ~0 >> 1), IFNULL(null, ~0 >> 1)) AS least_date; 
-- Returns: 5 

SELECT LEAST(IFNULL(null, ~0 >> 1), IFNULL(null, ~0 >> 1)) AS least_date 
-- Returns: @MAX_VALUE (If you need to use it as default value) 

SET @MAX_VALUE=~0 >> 1; 
SELECT LEAST(IFNULL(null, @MAX_VALUE), IFNULL(null, @MAX_VALUE)) AS least_date; 
-- Returns: @MAX_VALUE (If you need to use it as default value). Variables just makes it more readable! 

SET @MAX_VALUE=~0 >> 1; 
SELECT NULLIF(
    LEAST(IFNULL(null, @MAX_VALUE), IFNULL(null,@MAX_VALUE)), 
    @MAX_VALUE 
) AS least_date; 
-- Returns: NULL 

đó là cách ưa thích của tôi nếu

  • bạn có thể đảm bảo rằng ít nhất một cột không thể được NULL
  • trong trường hợp góc (tất cả các cột là NULL) bạn muốn có giá trị mặc định không lớn hơn bất kỳ giá trị nào hoặc có thể bị giới hạn ở một ngưỡng nhất định
  • Bạn có thể xử lý các biến để làm cho câu lệnh này dễ đọc hơn

Nếu bạn tự hỏi mình những gì ~0 >> 1 có nghĩa là: Đó chỉ là một bàn tay ngắn để nói "Hãy cho tôi số lượng lớn nhất có sẵn".Xem thêm: https://stackoverflow.com/a/2679152/2427579

Thậm chí tốt hơn, nếu bạn chỉ có hai cột, bạn có thể sử dụng:

SELECT LEAST(IFNULL(@column1, @column2), IFNULL(@column2, @column1)) AS least_date; 
-- Returns: NULL (if both columns are null) or the least value 
0

Tại sao không thiết lập giá trị của một cột là bằng với cột khác khi nó NULL?

SELECT LEAST(IFNULL(COL1, COL2), IFNULL(COL2, COL1)); 

với mã ở trên, giá trị null sẽ bị bỏ qua trừ khi cả hai đều rỗng.

ví dụ:

COL1 = NULL, col2 = 5

LEAST(IFNULL(NULL, 5), IFNULL(5, NULL)) -> LEAST(5, 5) -> 5 

COL1 = 3, col2 = NULL

LEAST(IFNULL(3, NULL), IFNULL(NULL, 3)) -> LEAST(3, 3) -> 3 

COL1 = NULL, col2 = NULL

LEAST(IFNULL(NULL, NULL), IFNULL(NULL, NULL)) -> LEAST(NULL, NULL) -> NULL 
Các vấn đề liên quan