1

問題:存在する値の間にサーバー用の最初の空きポートを取得します。空き地がない場合は、最高の+1を取ります。

追加:server_deleted = 1の場合、空きポートを取得できます。また、値の間にギャップがある場合は、フリーポートを使用する必要があります。where句にserver_typeを含める必要があります。最小値は最初のポート(例:9000)です。

今私のクエリは見えます:

SELECT server_port + 1
  FROM pro_servers s
 WHERE s.server_port <> 0
   AND s.server_type = 'ts3'
   AND s.server_deleted = 0
   AND NOT EXISTS
        ( SELECT s1.server_port
            FROM pro_servers s1
           WHERE s1.server_port <> 0
             AND s1.server_type = 'ts3'
             AND s1.server_port = s.server_port + 1
             AND s1.server_deleted = 0
        )
 ORDER BY server_port LIMIT 1

私はそれを行うためのより良い方法があると思います。このクエリの実行は非常に遅くなります。

たとえば、first = minimum = lowest = 9000、nextは9002、9003です。9001を取得する必要があります。9001を追加すると9004が取得されます。最初の値9000はテーブルに存在します。

サンプルデータ

+-----------+-------------+----------------+-------------+
| server_id | server_port | server_deleted | server_type |
+-----------+-------------+----------------+-------------+
|       151 |        9500 |              1 | teamspeak3  |
|      8459 |        9500 |              0 | teamspeak3  |
|       183 |        9501 |              1 | teamspeak3  |
|       264 |        9502 |              1 | teamspeak3  |
|      4155 |        9502 |              1 | teamspeak3  |
|      2707 |        9503 |              1 | teamspeak3  |
|      4160 |        9503 |              1 | teamspeak3  |
|       154 |        9504 |              1 | teamspeak3  |
|      4163 |        9504 |              1 | teamspeak3  |
|       285 |        9506 |              1 | teamspeak3  |
|      4167 |        9506 |              1 | teamspeak3  |
|      8454 |        9506 |              0 | teamspeak3  |
|       241 |        9507 |              1 | teamspeak3  |
|      4169 |        9507 |              1 | teamspeak3  |
|       188 |        9509 |              1 | teamspeak3  |
|      4177 |        9509 |              1 | teamspeak3  |
+-----------+-------------+----------------+-------------+

クエリ結果:9501。このポートを使用した場合、次に次のようになります:9502、9503、9504、9505、9507、9508、9509、9510など。

4

4 に答える 4

2
SELECT data.sPort
FROM 
  ((SELECT (s.server_port + 1) sPort
  FROM pro_servers s
  LEFT JOIN pro_servers sp1 ON sp1.server_port = s.server_port + 1
  WHERE (sp1.server_port IS NULL)
  ORDER BY sPort)

  UNION ALL

  (SELECT s.server_port sPost
  FROM pro_servers s
   GROUP BY s.server_port
   HAVING COUNT(s.server_port) = SUM(s.server_deleted)
  ORDER BY sPort)) AS data
ORDER BY data.sPort
LIMIT 1

SqlFiddle: http://sqlfiddle.com/#!2/12ab1/2

使い方

  1. 結合条件で左結合pro_servers、次のポートにある行を取得します。これらの行は、すべてのギャップからの最初のポートを示しています。ポート ID は として取得できます。pro_serversserver_port = server_port + 1nullserver_port + 1

  2. 削除されたポートをすべて取得します。

  3. ユニオン 1. と 2. を並べてserver_port、最初のものを取ります。

答えには 1 つの前提があります。番号が最も小さいポートが常に使用されます。そうでない場合は、そのポートを個別に確認します (または別のポートUNION ALLをクエリに追加します)。

于 2013-03-13T21:30:45.947 に答える
0

私は以下を使用するこのクエリを使用しますNOT EXISTS

SELECT MIN(server_port)+1
FROM pro_servers p1
WHERE
  p1.server_type = 'ts3' AND
  NOT EXISTS (SELECT server_port
              FROM   pro_servers p2
              WHERE  p1.server_port=p2.server_port-1
                     AND p1.server_type=p2.server_type
                     AND p2.server_deleted=0)

またはLEFT JOIN:を使用するこれ

SELECT MIN(p1.server_port)+1
FROM
  pro_servers p1 LEFT JOIN pro_servers p2
  ON p1.server_port=p2.server_port-1
     AND p1.server_type=p2.server_type
     AND p2.server_deleted=0
WHERE
  p2.server_port IS NULL
  AND p1.server_type='ts3'

こちらのフィドルをご覧ください。

于 2013-03-13T21:47:01.993 に答える
0

これが高速になるかどうかはわかりませんが、同じ条件を 2 回繰り返さないようにするのに役立ちます。

SELECT
  MAX(server_port) + 1 AS first_available_port
FROM (
  SELECT
    server_port,
    @row := @row + 1 AS row
  FROM
    pro_servers AS s,
    (SELECT @row := 0) AS x
  WHERE server_port <> 0
    AND server_type = 'ts3'
    AND server_deleted = 0
) AS s
GROUP BY
  server_port - row
ORDER BY
  server_port - row
LIMIT 1
;

内部クエリは、条件に一致する既存のポートを列挙します。これで、ポート番号と行番号の違いは、連続する行の同じグループに属する行に対して同じままになります。外側のクエリは、その差によってグループ化し、最初のグループの最も高いポート + 1 を返します。

于 2013-03-13T21:53:10.613 に答える