2011-07-18 33 views
0

我有這些表:的MySQL JOIN和COUNT不連貫

mysql> desc mod_asterisk_booking; 
+---------------+------------------+------+-----+---------+----------------+ 
| Field   | Type    | Null | Key | Default | Extra   | 
+---------------+------------------+------+-----+---------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| uid   | int(10) unsigned | NO |  | NULL |    | 
| server_id  | int(10) unsigned | NO |  | NULL |    | 
| date_call  | datetime   | NO |  | NULL |    | 
| participants | int(10) unsigned | NO |  | NULL |    | 
| ...                  | 
+---------------+------------------+------+-----+---------+----------------+ 

mysql> desc mod_asterisk_servers; 
+-------------------+------------------+------+-----+---------+----------------+ 
| Field    | Type    | Null | Key | Default | Extra   | 
+-------------------+------------------+------+-----+---------+----------------+ 
| id    | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| name    | varchar(32)  | NO |  | NULL |    | 
| channels_capacity | int(10) unsigned | NO |  | NULL |    | 
| ...                   | 
+-------------------+------------------+------+-----+---------+----------------+ 

mysql> desc mod_asterisk_server_phones; 
+------------------+------------------+------+-----+---------+----------------+ 
| Field   | Type    | Null | Key | Default | Extra   | 
+------------------+------------------+------+-----+---------+----------------+ 
| id    | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| server_id  | int(10) unsigned | NO |  | NULL |    | 
| phone_number  | varchar(15)  | NO |  | NULL |    | 
| phone_alias  | varchar(15)  | NO |  | NULL |    | 
| extension  | int(10) unsigned | NO |  | NULL |    | 
| is_toll_free  | tinyint(1)  | NO |  | 0  |    | 
| is_allow_foreign | tinyint(1)  | NO |  | 0  |    | 
+------------------+------------------+------+-----+---------+----------------+ 

的目標是獲取服務器(從mod_asterisk_servers),有可用於給定日期間隔足夠的通道。該查詢

SELECT s.*, 
     s.`channels_capacity` - IFNULL(SUM(b.`participants`), 0) as 'channels_available' 
    FROM `mod_asterisk_servers` as s 
    LEFT JOIN `mod_asterisk_booking` as b ON (b.server_id=s.id AND (b.date_call BETWEEN '2011-07-30 15:15:00' AND '2011-07-30 17:15:00')) 
GROUP BY s.id 
ORDER BY 'channels_available' DESC; 

可以返回類似:

+----+-------------+-----+------------------+--------------------+ 
| id | name  | ... |channels_capacity | channels_available | 
+----+-------------+-----+------------------+--------------------+ 
| 1 | Test server | ... |    150 |    140 | 
+----+-------------+-----+------------------+--------------------+ 

現在,我想一些列添加到該查詢;特別是與每個找到的服務器相關的電話號碼。電話號碼可以具有這些組合:

  • 本地電話號碼(is_toll_free=0 AND is_allow_foreign=0
  • 免費電話號碼,限定於一個給定的區域(is_toll_free=1 AND is_allow_foreign=0
  • 免費電話號碼,允許「擴展」區域(is_toll_free=1 AND is_allow_foreign=1

我嘗試這個查詢

SELECT s.*, 
     s.`channels_capacity` - IFNULL(SUM(b.`participants`), 0) as 'channels_available', 
     count(p1.phone_number) as 'local_phones', 
     count(p2.phone_number) as 'toll_free_phones', 
     count(p3.phone_number) as 'allow_foreign_phones' 
    FROM `mod_asterisk_servers` as s 
    LEFT JOIN `mod_asterisk_booking` as b ON (b.server_id=s.id AND (b.date_call BETWEEN '2011-07-30 15:15:00' AND '2011-07-30 17:15:00')) 
    LEFT JOIN `mod_asterisk_server_phones` as p1 ON (p1.server_id=s.id AND p1.is_toll_free=0 AND p1.is_allow_foreign=0) 
    LEFT JOIN `mod_asterisk_server_phones` as p2 ON (p2.server_id=s.id AND p2.is_toll_free=1 AND p2.is_allow_foreign=0) 
    LEFT JOIN `mod_asterisk_server_phones` as p3 ON (p3.server_id=s.id AND p3.is_toll_free=1 AND p3.is_allow_foreign=1) 
ORDER BY 'channels_available' DESC; 

但它返回

+----+-------------+-----+-------------------+--------------------+--------------+------------------+----------------------+ 
| id | name  | ... | channels_capacity | channels_available | local_phones | toll_free_phones | allow_foreign_phones | 
+----+-------------+-----+-------------------+--------------------+--------------+------------------+----------------------+ 
| 1 | Test server | ... |    150 |    140 |   2 |    2 |     2 | 
+----+-------------+-----+-------------------+--------------------+--------------+------------------+----------------------+ 

即使只有三個數字對於服務器:

mysql> select * from mod_asterisk_server_phones where server_id = 1; 
+----+-----------+----------------+-------------+-----------+--------------+------------------+ 
| id | server_id | phone_number | phone_alias | extension | is_toll_free | is_allow_foreign | 
+----+-----------+----------------+-------------+-----------+--------------+------------------+ 
| 1 |   1 | XXX-XXX-XXXX |    |  XXXX |   0 |    0 | 
| 2 |   1 | 1-800-XXX-XXXX |    |  XXXX |   1 |    0 | 
| 3 |   1 | 1-800-XXX-XXXX |    |  XXXX |   1 |    1 | 
+----+-----------+----------------+-------------+-----------+--------------+------------------+ 

也許有人有更好的理解SQL可以幫我找出這個嗎?

謝謝!

+1

我沒有讀過你的完整故事等,但我注意到你沒有使用「GROUP BY」子句來計數。因此,在您的查詢中添加「GROUP BY p1.server_id」之類的內容。 – Jules

+0

是的,但即使用'GROUP BY ...'查詢太多行也被查詢 –

回答

1

嘗試count(DISTINCT p1.phone_number)而不是count(p1.phone_number)(對於p2,p3也是如此)。並且不要忘記正確的GROUP BY

+0

啊!我不知道'DISTINCT'在組函數內部工作。謝謝! –