Pregunta

I am working on the following table:

CREATE TABLE `cons` (
  `Id` char(20) NOT NULL,
  `Client_ID` char(12) NOT NULL,
  `voice_cons` decimal(11,8) DEFAULT '0.00000000',
  `data_cons` int(11) DEFAULT '0',
  `day` date DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

I need to get some data from another table, cdr, which contains a row per event. This means every call or data connection has its own row.

+-----------+--------------+----------------+-------+
| Client_ID | Data_Up_Link | Data_Down_Link | Price |
+-----------+--------------+----------------+-------+
|         1 |           23 |             56 |     0 |
|         1 |           12 |              3 |     0 |
|         1 |            0 |              0 |     5 |
+-----------+--------------+----------------+-------+

I need to compute the total voice and data consumption for each Client_ID in my new cons table, but just keeping a single record for each Client_ID and day. To keep the question simple, I will consider just one day.

+-----------+-----------+------------+
| Client_ID | data_cons | voice_cons |
+-----------+-----------+------------+
|         1 |        94 |          5 |
+-----------+-----------+------------+

I have unsuccessfully tried the following, among many other (alias, .

insert into cons_day (Id, Client_ID, voice_cons, MSISDN, day)   
select 
concat(Client_ID,date_format(date,'%Y%m%d')), 
Client_ID, 
sum(Price) as voice_cons, 
date as day 
from cdr
where Type_Cdr='VOICE' 
group by Client_ID;

insert into cons_day (Id, Client_ID, data_cons, MSISDN, day)   
select 
    concat(Client_ID,date_format(date,'%Y%m%d')), 
    Client_ID, 
    sum(Data_Down_Link+Data_Up_Link) as data_cons, 
    Calling_Number as MSISDN, 
    date as day 
from cdr
where Type_Cdr='DATA' 
group by Client_ID
on duplicate key update data_cons=data_cons;

But I keep getting the values unchanged or receiving SQL errors. I would really appreciate a piece of advice.

Thank you very much in advance.

¿Fue útil?

Solución

First of all it seems that Id column in cons table is absolutely redundant. You already have ClientID and Day columns. Just make them PRIMARY KEY.

That being said the proposed table schema might look like

CREATE TABLE `cons` 
(
  `Client_ID` char(12) NOT NULL,
  `voice_cons` decimal(11,8) DEFAULT '0.00000000',
  `data_cons` int(11) DEFAULT '0',
  `day` date DEFAULT NULL,
  PRIMARY KEY (`Client_ID`, `day`)
);

Now you can use conditional aggregation to get your voice_cons and data_cons in one go

SELECT Client_ID, 
       SUM(CASE WHEN Type_CDR = 'VOICE' THEN price END) voice_cons,
       SUM(CASE WHEN Type_CDR = 'DATA'  THEN Data_Up_Link + Data_Down_Link END) data_cons,
       DATE(date) day
  FROM cdr
 GROUP BY Client_ID, DATE(date)

Note: you have to GROUP BY both by Client_ID and DATE(date)

Now the INSERT statement should look like

INSERT INTO cons (Client_ID, voice_cons, data_cons, day)
SELECT Client_ID, 
       SUM(CASE WHEN Type_CDR = 'VOICE' THEN price END) voice_cons,
       SUM(CASE WHEN Type_CDR = 'DATA'  THEN Data_Up_Link + Data_Down_Link END) data_cons,
       DATE(date) day
  FROM cdr
 GROUP BY Client_ID, DATE(date)
ON DUPLICATE KEY UPDATE voice_cons = VALUES(voice_cons), 
                        data_cons  = VALUES(data_cons);

Note: since now you simultaneously get both voice_cons and data_cons you might not need ON DUPLICATE KEY clause at all if you don't process data for the same dates multiple times.

Here is SQLFiddle demo

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top