sql >> データベース >  >> RDS >> Mysql

PHP MySQLは、列で最小の欠落番号を検出します

    Orderの場合 列にインデックスが付けられている場合、除外するLEFT JOINを使用してテーブル全体を読み取ることなく、SQLで最初に欠落している数値を取得できます。

    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
    

    2番目のクエリはMySQLによって最初のクエリに変換されます。したがって、それらは実質的に同等です。

    更新

    ストロベリーは良い点を述べました:最初に欠落している番号は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)は、そのクエリを適切に最適化できません。最初に欠落している番号が9であっても、インデックス付き(PK)1M行テーブルでは約1秒かかります。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. 価格のフロートまたは小数?

    2. アマゾンウェブサービス(AWS)の自動スケーリングの概要

    3. ビューcodeigniterでモデル関数を呼び出す

    4. concatを使用したpdo更新ステートメントが機能していません