Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

PHP MySQL tìm số bị thiếu nhỏ nhất trong cột

Nếu Order được lập chỉ mục, bạn có thể nhận được số bị thiếu đầu tiên với SQL mà không cần đọc bảng hoàn chỉnh bằng cách sử dụng loại trừ LEFT JOIN:

SELECT t1.`Order` + 1 AS firstMissingOrder
FROM tabla t1
LEFT JOIN tabla t2 ON t2.`Order` = t1.`Order` + 1
WHERE t2.`Order` IS NULL
  AND t1.`Order` <> (SELECT MAX(`Order`) FROM tabla)
ORDER BY t1.`Order`
LIMIT 1

hoặc (có thể trực quan hơn)

SELECT t1.`Order` + 1 AS firstMissingOrder
FROM tabla t1
WHERE NOT EXISTS (
    SELECT 1
    FROM tabla t2
    WHERE t2.`Order` = t1.`Order` + 1
) 
    AND t1.`Order` <> (SELECT MAX(`Order`) FROM tabla)
ORDER BY t1.`Order`
LIMIT 1

Truy vấn thứ hai sẽ được MySQL chuyển đổi thành truy vấn đầu tiên. Vì vậy, chúng thực tế ngang nhau.

Cập nhật

Strawberry đề cập đến một điểm hay:Số đầu tiên còn thiếu có thể là 1 , không được đề cập trong truy vấn của tôi. Nhưng tôi không thể tìm ra giải pháp, giải pháp này vừa - thanh lịch vừa nhanh chóng.

Chúng ta có thể đi theo hướng ngược lại và tìm kiếm số đầu tiên sau một khoảng cách. Nhưng sẽ cần tham gia lại bảng để tìm số hiện có cuối cùng trước khoảng cách đó.

SELECT IFNULL(MAX(t3.`Order`) + 1, 1) AS firstMissingOrder
FROM tabla t1
LEFT JOIN tabla t2 ON t2.`Order` = t1.`Order` - 1
LEFT JOIN tabla t3 ON t3.`Order` < t1.`Order`
WHERE t1.`Order` <> 1
  AND t2.`Order` IS NULL
GROUP BY t1.`Order`
ORDER BY t1.`Order`
LIMIT 1

MySQL (trong trường hợp của tôi là MariaDB 10.0.19) không thể tối ưu hóa truy vấn đó đúng cách. Mất khoảng một giây trên bảng hàng 1M được lập chỉ mục (PK), ngay cả khi số đầu tiên bị thiếu là 9. Tôi mong máy chủ ngừng tìm kiếm sau t1.Order=10 , nhưng nó không kết nối để làm điều đó.

Một cách khác, nhanh nhưng trông xấu (IMHO), là sử dụng truy vấn ban đầu trong một lựa chọn con chỉ khi Order=1 tồn tại. Nếu không, hãy trả về 1 .

SELECT CASE
    WHEN NOT EXISTS (SELECT 1 FROM tabla WHERE `Order` = 1) THEN 1
    ELSE (
        SELECT t1.`Order` + 1 AS firstMissingOrder
        FROM tabla t1   
        LEFT JOIN tabla t2 ON t2.`Order` = t1.`Order` + 1
        WHERE t2.`Order` IS NULL
          AND t1.`Order` <> (SELECT MAX(`Order`) FROM tabla)
        ORDER BY t1.`Order`
        LIMIT 1
    )
END AS firstMissingOrder

Hoặc sử dụng UNION

SELECT 1 AS firstMissingOrder FROM (SELECT 1) dummy WHERE NOT EXISTS (SELECT 1 FROM tabla WHERE `Order` = 1)
UNION ALL
SELECT firstMissingOrder FROM (
    SELECT t1.`Order` + 1 AS firstMissingOrder
    FROM tabla t1
    LEFT JOIN tabla t2 ON t2.`Order` = t1.`Order` + 1
    WHERE t2.`Order` IS NULL
      AND t1.`Order` <> (SELECT MAX(`Order`) FROM tabla)
    ORDER BY t1.`Order`
    LIMIT 1
) sub
LIMIT 1


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lịch PHP với các sự kiện lặp lại từ cơ sở dữ liệu MySQL

  2. Toán PHP trên dữ liệu SQL

  3. Làm thế nào để cập nhật một trang web mà không cần tải lại trang web bằng AJAX?

  4. Cách sử dụng orderby trên phần tử được kết hợp với phương thức Laravel Eloquent WITH

  5. Kết nối các ứng dụng ODBC với MySQL