I'm trying to find a way to add a country code to a database call record based on a phone number column. I have a table that contains countries and their dialing codes (called countries). I can query all records and append the country code, but I need to be able to filter and paginate the results.
I'm working with a system that I don't have a lot of control over, so adding new columns to the table or rewriting large chunks of code aren't really options. That's what I have to deal with.
Country/region table.
id | Name | Dial Code |
---|---|---|
1 | Ireland | 353 |
2 | USA | 1 |
Call record table.
id | Start Date Time | End Date Time | route_id | telephone number | duration_seconds |
---|---|---|---|---|---|
1 | 2014-12-18 18:51:12 | 2014-12-18 18:52:12 | twenty three | 3538700000 | 60 |
2 | 2014-12-18 17:41:02 | 2014-12-18 17:43:02 | 43 | 18700000 | 120 |
Routing table.
id | number | activated |
---|---|---|
twenty three | 1234567890 | 1 |
43 | 0987654321 | 1 |
I need to get the sum value of duration with all unique phone numbers grouped by route_id, route_number, but now we need to group these results by country_id so that we can group callers by country. I am using the below mysql query to get the sum value of duration, total number of unique phone numbers, all grouped by route_id, route_number. This query was written by another developer a long time ago.
SELECT phone_number, route_number, COUNT(callrecord_id) AS total_calls, SUM(duration_sec) AS total_duration, callrecord_join.route_id FROM routes RIGHT JOIN ( SELECT DATE(a.startdatetime) AS call_date, a.id AS callrecord_id, a.route_id AS route_id, a.phonenumber AS phone_number, a.duration_seconds as duration_sec, b.inboundnumber AS route_number, FROM callrecord AS a INNER JOIN routes AS b ON a.route_id = b.id WHERE DATE_FORMAT(a.startdatetime, '%Y-%m-%d') >= '2014-12-18' AND DATE_FORMAT(a.startdatetime, '%Y-%m-%d') <= '2014-12-18' AND b.isenabled = 1 ) AS callrecord_join ON routes.id = callrecord_join.route_id GROUP BY route_id, route_number LIMIT 10 offset 0;
I've done all the work of adding the country_id to the right join table so that I can group by country_id.
I know I can use php to iterate through each country and get the results using a where clause as shown below, but I can't paginate these results or filter them easily.
Left(a.phonenumber, strlen($dialling_code)) = $dialling_code
How do I add a column to a join table query containing country IDs using the country table so that I can group by route ID, route number, and country ID? As shown in the table below.
id | Start Date Time | End Date Time | route_id | telephone number | duration_seconds | country_id |
---|---|---|---|---|---|---|
1 | 2014-12-18 18:51:12 | 2014-12-18 18:52:12 | twenty three | 3538700000 | 60 | 1 |
2 | 2014-12-18 17:41:02 | 2014-12-18 17:43:02 | 43 | 18700000 | 120 | 2 |
The
RIGHT JOIN
fromroutes
tocallrecord_join
does nothing because you already have theINNER JOIN
subquery in between Theroutes
andcallrecord
are located on the right side of the join.You can use the join you described -
But it will give the same result:
It should be slightly cheaper.
You should test the inclusion of
countries
to ensure that any number incallrecord
is not added to more than one country. Some international dialing codes are ambiguous, so it depends on which dialing code list you use.Obviously, if your dataset is very large, you will need to batch the above query.
I hope I'm not oversimplifying things, but from my understanding of your question, the query is just:
Note that, assuming a suitable index is available, be careful to remove
DATE_FORMAT()
fromstartdatetime
to make these conditions controllable.