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,接下来是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. Left Join pro_serverswith pro_serverswith server_port = server_port + 1join 条件并取行,null在下一个端口中存在。这些行显示每个间隙的第一个端口。端口 ID 可以作为server_port + 1.

  2. 获取所有已删除的端口。

  3. 联合 1. 和 2.,按顺序server_port取第一个。

答案有一个假设 - 始终采用最低编号的端口。如果不是这样,请单独检查该端口(或将另一个添加UNION ALL到查询中)。

于 2013-03-13T21:30:45.947 回答
0

此外,您可以尝试索引表。

CREATE INDEX indexName ON tableName(field1 [,field2...]);

于 2013-03-13T21:45:35.007 回答
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

我不知道这是否会更快,但它肯定会帮助您避免重复相同的条件两次:

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
;

内部查询枚举匹配条件的现有端口。现在,对于属于同一组连续行的行,端口号和行号之间的差异将保持不变。外部查询按该差异分组并返回第一组的最高端口加一。

于 2013-03-13T21:53:10.613 回答