开发者

MySQL JOIN and COUNT not coherent

I have these tables :

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;
+------------------+------------------+------+-----+---------+--开发者_C百科--------------+
| 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       |                | 
+------------------+------------------+------+-----+---------+----------------+

The goal is to fetch a server (from mod_asterisk_servers) that has the enough channels available for a given date interval. This query

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;

could return something like :

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

Now, I'd like to add some columns to this query; notably the phone numbers associated with each server found. A phone number may have these combination :

  • local phone number (is_toll_free=0 AND is_allow_foreign=0)
  • toll free number, limited to a given region (is_toll_free=1 AND is_allow_foreign=0)
  • toll free number, allowing an "extended" region (is_toll_free=1 AND is_allow_foreign=1)

I tried this query

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;

but it returns

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

even though there are only three numbers for that server :

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 | 
+----+-----------+----------------+-------------+-----------+--------------+------------------+

Maybe someone with better understanding of SQL can help me figure out this one?

Thanks!


Try count(DISTINCT p1.phone_number) instead of count(p1.phone_number) (and the same for p2,p3). And don't forget the proper GROUP BY

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜