Question

my problem is that I don't even know if this kind of query is possible. I'll try to explain:

I have two tables regarding telephone calls, "Calls" and "Failed_Calls".

Important columns in both tables are "Destination" and "Route", but there are many more like Id_call and start_date and called_number and so on. I will omit filters regarding time periods to simplify. It is possible to have destinations in "Calls" not present in "Failed_Calls" and vice versa.

I want to get, for every possible Destination and Route couple, the calls count and the failed calls count, like the following code:

select c.Destination, c.Route, count(c.id_call) as Correct, null as Failed 
from Calls c
where c.Destination like ('Algeria%')
group by c.Destination, c.Route
union all
select f.Destination, f.Route, null, count(f.id_failed_call) as Failed
from Failed_Calls f
where f.Destination like ('Algeria%')
group by f.Destination, f.Route

It shows:

Destination    Route   Correct   Failed
Algeria        9       1         NULL
Algeria Mobile 9       4         NULL
Algeria Mobile 9       NULL      2

...which is correct, but I need to show the data on the two last rows on a single row, i.e., the count of both correct and failed calls for that destination and route.

I have tried with join, left join and with no join but I always get a bad count, something like the product of calls and failed calls for each couple. My best shot until now is:

select c.Destination, c.Route, count(distinct(c.id_call)) as Correct,
 count(distinct(f.id_failed_call)) as Failed
from Calls c, Failed_Calls f
where c.Destination like 'Algeria%'
 and f.Destination like 'Algeria%'
group by c.Destination, c.Route

...which returns the following:

Destination     Route     Correct    Failed
Algeria         9         1          2
Algeria Mobile  9         4          2

The "Correct" column is OK but the "Failed" column shows the sum of failed calls for all destinations returned, in every row (I have checked this with more destinations in the query).

If this kind of a query is possible, I wish someone could help me with it.

Was it helpful?

Solution

I haven't tried it in this case, but I've used a query like this before to sum up data from UNIONs.

select Destination, route, sum(Correct), sum(Failed ) from (
    select c.Destination, c.Route, count(c.id_call) as Correct, 0 as Failed 
    from Calls c
    where c.Destination like ('Algeria%')
    group by c.Destination, c.Route
    union all
    select f.Destination, f.Route, 0 as Correct, count(f.id_failed_call) as Failed
    from Failed_Calls f
    where f.Destination like ('Algeria%')
    group by f.Destination, f.Route) as temp_table
group by Destination, route;

OTHER TIPS

Try Something thing like :

select c.Destination, c.Route, SUM(c.id_call) as Correct,
SUM(case when f.id_failed_call is NULL then 0 else 1 end)) as Failed
from Calls c, Failed_Calls f
where c.Destination like 'Algeria%'
and f.Destination like 'Algeria%'
group by c.Destination, c.Route

You should be able to basically wrap your working query into an outer select, and group the rows there;

SELECT Destination, Route,
       COALESCE(SUM(Correct), 0) Correct, COALESCE(SUM(Failed), 0) Failed
FROM (
  SELECT c.Destination, c.Route, COUNT(c.id_call) as Correct, NULL AS Failed 
  FROM Calls c
  WHERE c.Destination like ('Algeria%')
  GROUP BY c.Destination, c.Route
  UNION ALL
  SELECT f.Destination, f.Route, NULL, COUNT(f.id_failed_call) AS Failed
  FROM Failed_Calls f
  WHERE f.Destination LIKE ('Algeria%')
  GROUP BY f.Destination, f.Route
)
GROUP BY Destination, Route;

Try

SELECT dr.DESTINATION,
       dr.ROUTE,
       IFNULL(c.CORRECT_COUNT, 0) AS CORRECT_COUNT,
       IFNULL(f.FAILED_COUNT, 0) AS FAILED_COUNT
  FROM (SELECT DISTINCT DESTINATION, ROUTE
          FROM CALLS
        UNION DISTINCT
        SELECT DISTINCT DESTINATION, ROUTE
          FROM FAILED_CALLS) dr
  LEFT OUTER JOIN (SELECT DESTINATION,
                          ROUTE,
                          COUNT(DISTINCT ID_CALL) AS CORRECT_COUNT
                     FROM CALLS
                     GROUP BY DESTINATION, ROUTE) c
    ON (c.DESTINATION = dr.DESTINATION AND
        c.ROUTE = dr.ROUTE)
  LEFT OUTER JOIN (SELECT DESTINATION,
                          ROUTE,
                          COUNT(DISTINCT ID_CALL) AS FAILED_COUNT
                     FROM FAILED_CALLS
                     GROUP BY DESTINATION, ROUTE) f
    ON (f.DESTINATION = dr.DESTINATION AND
        f.ROUTE = dr.ROUTE)

The dr subquery gets all possible combinations of DESTINATION and ROUTE - the use of UNION DISTINCT indicates that duplicates should be removed.

The c subquery then joins in the 'correct' count for each destination and route, if such a count exists.

The f subquery then joins in the 'failed' count for each destination and route, if such a count exists.

Sqlfiddle here.

Share and enjoy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top