Mysql
 sql >> база данни >  >> RDS >> Mysql

PHP MySQL намира най-малкото липсващо число в колоната

Ако Order колоната е индексирана, можете да получите първото липсващо число с SQL, без да четете цялата таблица, използвайки изключващ 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

или (може би по-интуитивно)

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

Втората заявка ще бъде преобразувана от MySQL в първата. Така че те са практически равни.

Актуализиране

Strawberry спомена добра точка:първото липсващо число може да е 1 , което не е обхванато в моята заявка. Но не успях да намеря решение, което е едновременно - елегантно и бързо.

Можем да отидем по обратния път и да търсим първото число след празнина. Но ще трябва да се присъедините отново към таблицата, за да намерите последното съществуващо число преди тази празнина.

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 (в моя случай MariaDB 10.0.19) не е в състояние да оптимизира тази заявка правилно. Отнема около една секунда за индексирана (PK) таблица с редове от 1M, въпреки че първото липсващо число е 9. Очаквам сървърът да спре да търси след t1.Order=10 , но изглежда да не се прави това.

Друг начин, който е бърз, но изглежда грозен (IMHO), е да използвате оригиналната заявка в подселекция само ако Order=1 съществува. В противен случай върнете 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

Или чрез 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. jQuery UI Sortable, след което запишете поръчка в база данни

  2. MySQL система за проследяване

  3. Условно сортиране в MySQL?

  4. Първият html ред не се показва

  5. mysql cte . използването на with и вмъкване предупреждава за синтактична грешка