2013-03-13 36 views
1

問題:在存在值之間爲服務器獲取第一個空閒端口。如果沒有空閒的地方,則取最高+ 1.MySQL之間存在的第一個空閒數值

額外:如果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等

+0

EXPLAIN計劃?你有索引嗎? – 2013-03-13 21:15:39

+0

第一個數字:=最小數字:=最小數字? – wildplasser 2013-03-13 21:16:57

+1

請發佈數據樣本和預期的查詢結果。 – 2013-03-13 21:25:08

回答

1
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_serverspro_serversserver_port = server_port + 1連接條件,並採取行,其中有在下一個端口null。這些行顯示每個間隙的第一個端口。端口ID可以被視爲server_port + 1

  2. 取出所有已刪除的端口。

  3. 聯合1.和2.,訂購併採取第一個。

對於答案有一個假設 - 總是採用編號最小的端口。如果不是這樣,請單獨檢查該端口(或將另一個UNION ALL添加到查詢中)。

+1

使用'DISTINCT'關鍵字。 – MarcinJuraszek 2013-03-13 21:48:47

+0

DISTINCT或UNION沒有全部? – Dream 2013-03-13 22:00:47

+0

'SELECT DISTINCT s.server_port sPost' – MarcinJuraszek 2013-03-13 22:01:50

0

此外,您可以嘗試索引表。

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

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' 

請參閱小提琴here

+0

我們不應該寫第一個端口,因爲它與服務器類型有關。 – Dream 2013-03-13 21:55:02

+0

@AdamMiaśkiewicz是第一個已經存在的價值?請看我更新的答案。它幾乎與您的查詢相同,我只使用MAX()聚合函數而不是ORDER BY和LIMIT 1 – fthiella 2013-03-13 22:04:26

+0

是的,第一個值已經被插入。您的查詢速度不及@MarcinJuraszek的答案。 – Dream 2013-03-13 22:29:18

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 
; 

內部查詢列舉符合條件的現有端口。現在,對於屬於同一組連續行的行,端口號和行號之間的差異將保持不變。外部查詢按該差異進行分組,並返回第一組的最高端口加1。

相關問題