MySQL database : how to write SQL for several tables - mysql
I need to create a view for client shipment documents which contains next info:
good name,
good count
good price.
Price may be different from one purchase agreement to other. For each purchase agreement may exists several shipments. Each good item in client_shipment_details may has serial number, but client_shipment document
keeps just total count of such kind of good.
This is my tables:
purchase_agreement;
+------------------------------+--------------+------+-----+---------+-------- --------+
| Field | Type | Null | Key | Default | Extra |
+------------------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| purchase_agreement_status_id | bigint(20) | YES | MUL | NULL | |
+------------------------------+--------------+------+-----+---------+----------------+
purchase_agreement_details;
+-----------------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| count | int(11) | NO | | NULL | |
| price | float | NO | | NULL | |
| purchase_agreement_id | bigint(20) | YES | MUL | NULL | |
| good_id | bigint(20) | YES | MUL | NULL | |
+-----------------------+------------+------+-----+---------+----------------+
goods;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
client_shipment;
-----------------------+--------------+------+-----+---------+---------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| jhi_date | datetime | YES | | NULL | |
| purchase_agreement_id | bigint(20) | YES | MUL | NULL | |
+-----------------------+--------------+------+-----+---------+----------------+
client_shipment_details;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
|
| serial_number | varchar(255) | YES | | NULL | |
| client_shipment_id | bigint(20) | YES | MUL | NULL | |
| good_id | bigint(20) | YES | MUL | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
This is my query :
SELECT
temp1.cs_id, temp1.good_id, temp1.count, temp1.price,good.name
FROM
(
SELECT csd.cs_id AS cs_id, csd.good_id AS good_id, csd.count AS count, pad.price AS price
FROM
(
SELECT client_shipment_id AS cs_id, good_id, count(*) AS count
FROM client_shipment_details
GROUP BY client_shipment_id, good_id
) AS csd
LEFT JOIN
(
SELECT pad.good_id AS good_id, pad.price AS price, cs.id AS cs_id
FROM purchase_agreement_details pad
JOIN client_shipment cs ON pad.purchase_agreement_id = cs.purchase_agreement_id
) AS pad ON csd.good_id = pad.good_id
GROUP BY cs_id,good_id
) AS temp1
JOIN goods ON temp1.good_id = good.id
ORDER BY cs_id,good_id;
Some test data:
insert into purchase_agreement values
(1,1),
(2,1);
insert into purchase_agreement_details values
(1,2,100,1,1),
(2,4,200,1,2),
(3,6,300,1,3),
(4,7,400,1,4),
(5,3,110,2,1),
(6,8,210,2,2),
(7,4,310,2,3),
(8,5,410,2,4);
insert into goods values
(1,"desk"),
(2,"sofa"),
(3,"chair"),
(4,"bed");
insert into client_shipment values
(1,'2019-02-21 09:57:00',1),
(2,'2019-02-21 09:57:00',1),
(3,'2019-02-21 09:57:00',2),
(4,'2019-02-21 09:57:00',2);
insert into client_shipment_details values
(1,"1-0001",1,1),
(2,"1-0002",1,1),
(3,"2-0001",1,2),
(4,"2-0002",1,2),
(5,"3-0001",1,3),
(6,"3-0002",1,3),
(7,"4-0001",1,4),
(8,"4-0002",1,4),
(9,"1-0003",2,1),
(10,"1-0004",2,1),
(11,"2-0003",2,2),
(12,"2-0004",2,2),
(13,"3-0003",2,3),
(14,"3-0004",2,3),
(15,"4-0003",2,4),
(16,"4-0004",2,4),
(17,"1-0005",3,1),
(18,"1-0006",3,1),
(19,"2-0005",3,2),
(20,"2-0006",3,2),
(21,"3-0005",3,3),
(22,"3-0006",3,3),
(23,"4-0005",3,4),
(24,"4-0006",3,4),
(25,"1-0007",4,1),
(26,"1-0008",4,1),
(27,"2-0007",4,2),
(28,"2-0008",4,2),
(29,"3-0007",4,3),
(30,"3-0008",4,3),
(31,"4-0007",4,4),
(32,"4-0008",4,4);
I'd like to get such result :
client_shipment_id good_name price count
1 desk 100 2
1 sofa 200 2
1 chair 300 2
1 bed 400 2
2 desk 100 2
2 sofa 200 2
2 chair 300 2
2 bed 400 2
3 desk 110 2
3 sofa 210 2
3 chair 310 2
3 bed 410 2
4 desk 110 2
4 sofa 210 2
4 chair 310 2
4 bed 410 2
Related
Calculate difference between two row amount in MySQL
I am having a table with which calculates balance, where I have these columns in the table: > describe tbl_credit_log +------------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | visitor_id | int(10) unsigned | YES | MUL | NULL | | | post_owner_id | int(10) unsigned | YES | MUL | NULL | | | post_id | int(10) unsigned | YES | MUL | NULL | | | balance | double(50,6) | YES | | NULL | | | credits | double(50,6) | YES | | NULL | | | debits | double(50,6) | YES | | NULL | | | trans_id | varchar(255) | NO | | NULL | | | trans_amount | double(50,6) | YES | | NULL | | | earningtype | varchar(15) | NO | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +------------------+------------------+------+-----+---------+----------------+ Where here is the few entries from which I want to do the calculations : +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ | id | visitor_id | post_owner_id | post_id | advertisement_id | balance | credits | debits | created_at | +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ | 4331666 | 11006 | 11 | NULL | NULL | 3639.624400 | 22.500000 | NULL | 2018-08-10 05:45:37 | | 4364034 | 7206 | 11 | NULL | NULL | 5139.607900 | 22.500000 | NULL | 2018-08-10 11:02:52 | | 4377238 | 4353 | 11 | NULL | NULL | 5162.107900 | 22.500000 | NULL | 2018-08-10 12:52:01 | | 4485288 | 9664 | 11 | NULL | NULL | 5184.607900 | 22.500000 | NULL | 2018-08-11 08:58:19 | | 4544185 | 11709 | 11 | NULL | NULL | 5207.107900 | 22.500000 | NULL | 2018-08-11 19:06:52 | | 4550728 | 11970 | 11 | NULL | NULL | 5229.607900 | 22.500000 | NULL | 2018-08-11 20:39:36 | | 4607317 | 12021 | 11 | NULL | NULL | 5252.107900 | 22.500000 | NULL | 2018-08-12 07:29:17 | | 4629660 | 11926 | 11 | NULL | NULL | 5274.607900 | 22.500000 | NULL | 2018-08-12 09:18:56 | | 4725299 | 12088 | 11 | NULL | NULL | 5297.107900 | 22.500000 | NULL | 2018-08-13 01:54:53 | | 4725347 | 10253 | 11 | NULL | NULL | 5319.607900 | 22.500000 | NULL | 2018-08-13 08:29:46 | | 4725357 | 12140 | 11 | NULL | NULL | 5342.107900 | 22.500000 | NULL | 2018-08-13 09:27:44 | +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ here we have difference (more then 50) in amount on id number4364034 which I want to find in whole database where user id will be post_owner_id as foreign key. I want to get all the post_owner_id who have difference in the amount and their created_at. So the expected results will be something like this +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ | id | visitor_id | post_owner_id | post_id | advertisement_id | balance | credits | debits | created_at | +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ | 4364034 | 7206 | 11 | NULL | NULL | 5139.607900 | 22.500000 | NULL | 2018-08-10 11:02:52 | +---------+------------+---------------+---------+------------------+-------------+-----------+--------+---------------------+ here we will have multiple post_owner_id. I am showing one post_owner_id because this result is only of one post owner id. But I want to get different post owner id who have difference balance is more then 50. I am not able to figure out how can I do this. I want to compare prices on group_by post_owner_id and get the row where the difference amount is.
Consider the following: DROP TABLE IF EXISTS my_table; CREATE TABLE my_table (id SERIAL PRIMARY KEY ,balance DECIMAL(12,6) NOT NULL ,created_at timestamp NOT NULL ); INSERT INTO my_table VALUES (4331666,3639.624400,'2018-08-10 05:45:37'), (4364034,5139.607900,'2018-08-10 11:02:52'), (4377238,5162.107900,'2018-08-10 12:52:01'), (4485288,5184.607900,'2018-08-11 08:58:19'), (4544185,5207.107900,'2018-08-11 19:06:52'), (4550728,5229.607900,'2018-08-11 20:39:36'), (4607317,5252.107900,'2018-08-12 07:29:17'), (4629660,5274.607900,'2018-08-12 09:18:56'), (4725299,5297.107900,'2018-08-13 01:54:53'), (4725347,5319.607900,'2018-08-13 08:29:46'), (4725357,5342.107900,'2018-08-13 09:27:44'); Option 1: SELECT a.* FROM ( SELECT x.* , MIN(y.id) y_id FROM my_table x JOIN my_table y ON y.created_at > x.created_at GROUP BY x.id ) a JOIN my_table b ON b.id = a.y_id AND b.balance > a.balance + 50; +---------+-------------+---------------------+---------+ | id | balance | created_at | y_id | +---------+-------------+---------------------+---------+ | 4331666 | 3639.624400 | 2018-08-10 05:45:37 | 4364034 | +---------+-------------+---------------------+---------+ Option 2: SELECT id , balance , created_at FROM ( SELECT x.* , #i<balance-50 i , #i:=balance FROM my_table x , (SELECT #i:=null) vars ORDER BY created_at ) n WHERE i = 1; +---------+-------------+---------------------+ | id | balance | created_at | +---------+-------------+---------------------+ | 4364034 | 5139.607900 | 2018-08-10 11:02:52 | +---------+-------------+---------------------+ You can adapt either of the techniques above to return either row
Auto Increment a column in Mysql 5.7 according to another column in table
I have a table like this +------------------+------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------------+------+-----+-------------------+-----------------------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | user_id | int(10) unsigned | NO | | NULL | | | arena_ids | json | NO | | NULL | | | organization_id | int(10) unsigned | NO | MUL | NULL | | | type | tinyint(4) | NO | | NULL | | | registration_fee | double | YES | | NULL | | | tax_group_id | int(10) unsigned | YES | MUL | NULL | | | from_date | date | YES | | NULL | | | to_date | date | YES | | NULL | | | status | varchar(10) | YES | | NULL | | | comments | varchar(100) | YES | | NULL | | | created_at | datetime | NO | | CURRENT_TIMESTAMP | | | updated_at | datetime | YES | | NULL | on update CURRENT_TIMESTAMP | | deleted_at | datetime | YES | | NULL | | +------------------+------------------+------+-----+-------------------+-----------------------------+ Now in this table I have to add one more column serial number and that serial number will auto_increment but in my case it is something different I have to increment serial_number until organization_id changes and if organization_id changes so now again serial_number starts from 1 again. `serial_number` `organization_id` 1 1 2 1 1 2 3 1 2 2 while i was reading the documentation I found some example like this but I here I have to update not create CREATE TABLE animals ( grp ENUM('fish','mammal','bird') NOT NULL, id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (grp,id) ) +--------+----+---------+ | grp | id | name | +--------+----+---------+ | fish | 1 | lax | | mammal | 1 | dog | | mammal | 2 | cat | | mammal | 3 | whale | | bird | 1 | penguin | | bird | 2 | ostrich | +--------+----+---------+ How to achieve this thing in update query .
mysql query using 4 tables to produce small report
I'm having trouble getting a query to work. 4 tables are used in this query. I want a report looking like this... Name Success Failure jdn 5 1 wer 0 3 I want to produce data for the last 24 hours. Here is a sample query I tried and didn't work. select r.name as jid, i.id as theid, (select sum(counter) as scount from WebServicesIfSummarySuccess where id=theid and dtime between date_sub(now(),interval 24 hour) and now() and sum(counter) >0 and sum(counter) is not null group by id ) as success, (select sum(counter) as fcount from WebServicesIfSummaryFailure where id=theid and dtime between date_sub(now(),interval 24 hour) and now() and sum(counter) >0 and sum(counter) is not null group by id ) as failure from router r, interface i where r.rid = i.rid and r.name like '%wi%' ; Here are the table layouts. router +-------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+----------------+ | rid | int(11) unsigned | NO | PRI | NULL | auto_increment | | name | char(120) | NO | MUL | | | | pop | char(10) | NO | MUL | | | | popid | tinyint(3) unsigned | NO | | 0 | | +-------+---------------------+------+-----+---------+----------------+ interface +-------------+---------------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | name | char(255) | NO | MUL | | | | rid | int(11) | NO | MUL | 0 | | | speed | bigint(11) | YES | | NULL | | | description | char(255) | YES | | NULL | | | status | enum('active','inactive') | YES | | active | | +-------------+---------------------------+------+-----+---------+----------------+ Failure and Success are 2 separate tables +---------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+------------------+------+-----+---------+-------+ | id | int(10) unsigned | NO | PRI | NULL | | | dtime | datetime | NO | PRI | NULL | | | counter | bigint(20) | NO | | NULL | | | rate | int(11) | YES | | NULL | | +---------+------------------+------+-----+---------+-------+
How to make this SQL query faster?
I have the following query: SELECT DISTINCT `movies_manager_movie`.`id`, `movies_manager_movie`.`title`, `movies_manager_movie`.`original_title`, `movies_manager_movie`.`synopsis`, `movies_manager_movie`.`keywords`, `movies_manager_movie`.`release_date`, `movies_manager_movie`.`rating`, `movies_manager_movie`.`poster_web_url`, `movies_manager_movie`.`has_poster`, `movies_manager_movie`.`number`, `movies_manager_movie`.`has_sources`, `movies_manager_movie`.`season_id`, `movies_manager_movie`.`created`, `movies_manager_movie`.`updated`, `movies_manager_moviecache`.`activity_name` FROM `movies_manager_movie` LEFT OUTER JOIN `movies_manager_moviecache` ON (`movies_manager_movie`.`id` = `movies_manager_moviecache`.`movie_id`) WHERE (`movies_manager_movie`.`has_sources` = 1 AND (`movies_manager_moviecache`.`team_member_id` IN ( SELECT U0.`id` FROM `movies_manager_movieteammember` U0 INNER JOIN `movies_manager_movieteammemberactivity` U1 ON (U0.`id` = U1.`team_member_id`) WHERE U1.`movie_id` = 3588 ) AND `movies_manager_movie`.`number` IS NULL ) AND NOT (`movies_manager_movie`.`id` = 3588 )) ORDER BY `movies_manager_moviecache`.`activity_name` DESC LIMIT 3; This query can take up to 3 seconds and I'm very surprise since I got indexes everywhere and no more than 35 rows in each of my MyIsam tables, using the latest MySQL version. I cached everything I could but I have at least to run this one 20000 times every day, which is approximately 16 h of waiting for loading. And I'm pretty sure none of my user (nor Google Bot) appreciate a 4 secondes waiting time for each page loading. What could I do to make it faster ? I thought about duplicating field from movie to moviecache since the all purpose of movie cache is to denormalize to complex join already. I tried inlining the subquery to a list of ID but it surprisingly doubled the time of the query. Tables: +----------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | title | varchar(120) | NO | UNI | NULL | | | original_title | varchar(120) | YES | | NULL | | | synopsis | longtext | YES | | NULL | | | keywords | varchar(120) | YES | | NULL | | | release_date | date | YES | | NULL | | | rating | int(11) | NO | | NULL | | | poster_web_url | varchar(255) | YES | | NULL | | | has_poster | tinyint(1) | NO | | NULL | | | number | int(11) | YES | | NULL | | | season_id | int(11) | YES | MUL | NULL | | | created | datetime | NO | | NULL | | | updated | datetime | NO | | NULL | | | has_sources | tinyint(1) | NO | | NULL | | +----------------+--------------+------+-----+---------+----------------+ +---------------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(120) | NO | UNI | NULL | | | biography | longtext | YES | | NULL | | | birth_date | date | YES | | NULL | | | picture_web_url | varchar(255) | YES | | NULL | | | allocine_link | varchar(255) | YES | | NULL | | | created | datetime | NO | | NULL | | | updated | datetime | NO | | NULL | | | has_picture | tinyint(1) | NO | | NULL | | | biography_linkyfied | longtext | YES | | NULL | | +---------------------+--------------+------+-----+---------+----------------+ +----------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | movie_id | int(11) | NO | MUL | NULL | | | tag_slug | varchar(100) | YES | MUL | NULL | | | team_member_id | int(11) | YES | MUL | NULL | | | cast_rank | int(11) | YES | | NULL | | | activity_name | varchar(30) | YES | MUL | NULL | | +----------------+--------------+------+-----+---------+----------------+ Mysql tells me it's a slow query: # Query_time: 3 Lock_time: 0 Rows_sent: 9 Rows_examined: 454128
Move movies_manager_movieteammemberactivity and movies_manager_movieteammember to your main join statement (so that you're doing a left outer between movies_manager_movie and the inner join product of the other 3 tables). This should speed up your query considerably.
Try this: SELECT `movies_manager_movie`.`id`, `movies_manager_movie`.`title`, `movies_manager_movie`.`original_title`, `movies_manager_movie`.`synopsis`, `movies_manager_movie`.`keywords`, `movies_manager_movie`.`release_date`, `movies_manager_movie`.`rating`, `movies_manager_movie`.`poster_web_url`, `movies_manager_movie`.`has_poster`, `movies_manager_movie`.`number`, `movies_manager_movie`.`has_sources`, `movies_manager_movie`.`season_id`, `movies_manager_movie`.`created`, `movies_manager_movie`.`updated`, ( SELECT `movies_manager_moviecache`.`activity_name` FROM `movies_manager_moviecache` WHERE (`movies_manager_movie`.`id` = `movies_manager_moviecache`.`movie_id` AND (`movies_manager_moviecache`.`team_member_id` IN ( SELECT U0.`id` FROM `movies_manager_movieteammember` U0 INNER JOIN `movies_manager_movieteammemberactivity` U1 ON (U0.`id` = U1.`team_member_id`) WHERE U1.`movie_id` = 3588 ) AND `movies_manager_movie`.`number` IS NULL ) ) LIMIT 1) AS `activity_name` FROM `movies_manager_movie` WHERE (`movies_manager_movie`.`has_sources` = 1 AND NOT (`movies_manager_movie`.`id` = 3588 )) ORDER BY `activity_name` DESC LIMIT 3; Let me know how that performs
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; +------------------+------------------+------+-----+---------+----------------+ | 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