Return results for all months in range

4

I have the following query :

SELECT 
    CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) as DECIMAL(12,2)) AS TEMPO_CORRETO,
    MONTHNAME(ta2.change_time) AS MES,
    MONTH(ta2.change_time) AS NUMEROMES,
    t2.customer_id as EMPRESA
FROM 
    otrs.ticket t2
    LEFT JOIN otrs.time_accounting as ta2 ON t2.id = ta2.ticket_id
    LEFT JOIN otrs.ticket_type as tt2 ON t2.type_id = tt2.id
    LEFT JOIN otrs.service as s2 ON t2.service_id = s2.id   
WHERE
    ta2.change_time between '2018-01-01' AND '2018-04-30' AND
    t2.customer_id = 'ZSCHIMMER SCHWARZ' AND
    tt2.name = 'CONTRATO PCH'
GROUP BY 
    MONTHNAME(ta2.change_time),
    MONTH(ta2.change_time),
    EMPRESA
ORDER BY 
    NUMEROMES

And I'm getting the following result:

ButinmyqueryI'mselectingtheperiodfromJanuarytoApril,butinJanuaryIdonothavearecord,myneedwouldbetoreturnthefollowing:

How could I do this?

    
asked by anonymous 18.05.2018 / 18:53

4 answers

6

First you need to generate the sequence of months:

SELECT m.mes, MONTHNAME(STR_TO_DATE(m.mes, '%m')) AS nome_mes
FROM (
SELECT d1+d2*10 AS mes FROM
   (SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
     UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t1,
   (SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
     UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t2
LIMIT 12 OFFSET 1 ) AS m  

Then you give the select in the months table, with the outer join in your data table, it would look something like this:

SELECT 
    CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) AS DECIMAL(12,2)) AS TEMPO_CORRETO,
    MONTHNAME(STR_TO_DATE(m.mes, '%m')) AS MES,
    m.mes AS NUMEROMES,
    t2.customer_id AS EMPRESA
FROM 
    SELECT d1+d2*10 AS mes FROM
   (SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
     UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t1,
   (SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
     UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t2
LIMIT 12 OFFSET 1 ) AS m   
    LEFT JOIN otrs.time_accounting AS ta2 ON MONTH(ta2.change_time) = m.mes
    LEFT JOIN otrs.ticket t2 ON t2.id = ta2.ticket_id
    LEFT JOIN otrs.ticket_type AS tt2 ON t2.type_id = tt2.id
    LEFT JOIN otrs.service AS s2 ON t2.service_id = s2.id   
WHERE
    ta2.change_time BETWEEN '2018-01-01' AND '2018-04-30' AND
    t2.customer_id = 'ZSCHIMMER SCHWARZ' AND
    tt2.name = 'CONTRATO PCH'
GROUP BY 
    MONTHNAME(ta2.change_time),
    MONTH(ta2.change_time),
    EMPRESA
ORDER BY 
    NUMEROMES

ps. I did not consider the year

Update: link

After much conversation (see chat) I came to a query that I believe is the solution:

select

m.mes,
CAST(SUM(CASE WHEN s.name LIKE '%Servidores' THEN (coalesce(ta.time_unit,0) * 1.5)/ 60 ELSE coalesce(ta.time_unit,0)/60 END) AS DECIMAL(12, 2)) AS TEMPO_CORRETO,
tk2.customer_id

From

(Select 1 as mes union Select 2 union Select 3 union Select 4 union Select 5 union Select 6 union Select 7 union Select 8 union Select 9 union Select 10 union Select 11 union Select 12) as m

left outer join time_accounting ta on MONTH(ta.change_time) = m.mes 
left outer join ticket tk2 on ta.ticket_id = tk2.id 
                           and tk2.customer_id = 'ZSCHIMMER SCHWARZ' 
                           and tk2.type_id = 11
left outer join service AS s ON tk2.service_id = s.id

WHERE m.mes BETWEEN MONTH('2018-01-01') AND MONTH('2018-07-30')


GROUP BY m.mes,tk2.customer_id

order by m.mes

Available at DBFiddle

  

EDIT: 05/28/2018

Refile the query, this time showing the client name on all lines, even if it does not have records in the month:

SELECT
MONTHNAME(STR_TO_DATE(meses.mes, '%m')) AS MES,
meses.mes as mes_numero,
CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN ( coalesce(ta.time_unit,0) * 1.5)/ 60 ELSE coalesce(ta.time_unit,0)/60 END) AS DECIMAL(12, 2)) AS TEMPO_CORRETO,
meses.customer_id as empresa
FROM
(Select distinct
  m.mes,
  t2.customer_id
From (SELECT d1+d2*10 AS mes FROM 
(SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t1, 
(SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t2 
LIMIT 12 OFFSET 1 ) AS m
Cross Join ticket t2
WHERE t2.customer_id = 'ZSCHIMMER SCHWARZ') as meses
LEFT JOIN ticket t on t.customer_id = meses.customer_id
                   and t.type_id = 11
LEFT JOIN time_accounting ta on ta.ticket_id = t.id 
                             and MONTH(ta.change_time) = meses.mes
                             and ta.change_time BETWEEN '2018-01-01' AND '2018-07-30'

LEFT JOIN service AS s2 ON t.service_id = s2.id
WHERE meses.mes BETWEEN MONTH('2018-01-01') AND MONTH('2018-07-30')
GROUP BY   meses.mes, meses.customer_id    
ORDER BY meses.mes
  

Result:

mes_numero  TEMPO_CORRETO   empresa
1           0               ZSCHIMMER SCHWARZ
2           7.39            ZSCHIMMER SCHWARZ
3           23.29           ZSCHIMMER SCHWARZ
4           3.18            ZSCHIMMER SCHWARZ
5           0               ZSCHIMMER SCHWARZ
6           0               ZSCHIMMER SCHWARZ
7           0               ZSCHIMMER SCHWARZ

I put it in DBFiddle

    
18.05.2018 / 19:41
2

You can create a table of months as it would make your life easier:

CREATE TABLE mes (
  id INT,
  mes VARCHAR(10)
);

INSERT INTO mes VALUES(1, 'JANEIRO'),
                      (2, 'FEVEREIRO'),
                      (3, 'MARÇO'),
                      (4, 'ABRIL'),
                      (5, 'MAIO'),
                      (6, 'JUNHO'),
                      (7, 'JULHO'),
                      (8, 'AGOSTO'),
                      (9, 'SETEMBRO'),
                      (10, 'OUTUBRO'),
                      (11, 'NOVEMBRO'),
                      (12, 'DEZEMBRO');

Then use this table created directly in FROM , so you can display the values independently of the links to the other tables:

...
FROM mes m
...

In the next step, link the other tables with LEFT JOIN , which will limit the requirement:

...
LEFT JOIN time_accounting AS ta2 ON MONTH(ta2.change_time) = m.id
LEFT JOIN ticket t2 ON t2.id = ta2.ticket_id
LEFT JOIN ticket_type AS tt2 ON t2.type_id = tt2.id
LEFT JOIN service AS s2 ON t2.service_id = s2.id
...

In% with% you should consider that the tables used in WHERE can have OR NOT records, so you should check if it is LEFT :

...
WHERE (t2.id IS NULL OR t2.customer_id = 'ZSCHIMMER SCHWARZ') 
  AND (tt2.id IS NULL OR tt2.name = 'CONTRATO PCH') 
...

I recommend that the date filter be ugly per month, so whatever is not inside the filter will not be shown:

...
AND m.id BETWEEN MONTH('2018-01-01') AND MONTH('2018-07-30')
...

The resulting% w /% would be:

SELECT m.id,
       m.mes,
       CAST(SUM(CASE
                  WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5) / 60
                  ELSE ta2.time_unit/60
                END) AS DECIMAL(12, 2)) AS TEMPO_CORRETO,
       t2.customer_id AS EMPRESA
  FROM mes m
  LEFT JOIN time_accounting AS ta2 ON MONTH(ta2.change_time) = m.id
  LEFT JOIN ticket t2 ON t2.id = ta2.ticket_id
  LEFT JOIN ticket_type AS tt2 ON t2.type_id = tt2.id
  LEFT JOIN service AS s2 ON t2.service_id = s2.id
 WHERE (t2.id IS NULL OR t2.customer_id = 'ZSCHIMMER SCHWARZ')
   AND (tt2.id IS NULL OR tt2.name = 'CONTRATO PCH')
   AND m.id BETWEEN MONTH('2018-01-01') AND MONTH('2018-07-30')
 GROUP BY m.mes, m.id, t2.customer_id
 ORDER BY m.id
    
21.05.2018 / 20:57
0

Correction: Add another condition AND CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) as DECIMAL(12,2)) > 0

SELECT 
    CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) as DECIMAL(12,2)) AS TEMPO_CORRETO,
    MONTHNAME(ta2.change_time) AS MES,
    MONTH(ta2.change_time) AS NUMEROMES,
    t2.customer_id as EMPRESA
FROM 
    otrs.ticket t2
    LEFT JOIN otrs.time_accounting as ta2 ON t2.id = ta2.ticket_id
    LEFT JOIN otrs.ticket_type as tt2 ON t2.type_id = tt2.id
    LEFT JOIN otrs.service as s2 ON t2.service_id = s2.id   
WHERE
    ta2.change_time between '2018-01-01' AND '2018-04-30' AND
    t2.customer_id = 'ZSCHIMMER SCHWARZ' AND
    tt2.name = 'CONTRATO PCH' AND
    CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) as DECIMAL(12,2)) > 0
GROUP BY 
    MONTHNAME(ta2.change_time),
    MONTH(ta2.change_time),
    EMPRESA
ORDER BY 
    NUMEROMES
    
18.05.2018 / 19:22
0

If you invert the otrs.ticket t2 table with otrs.time_accounting ta2 would not it work?

Edited

SELECT 
    CAST(SUM(CASE WHEN s2.name LIKE '%Servidores' THEN (ta2.time_unit * 1.5)/60 ELSE ta2.time_unit/60 END) as DECIMAL(12,2)) AS TEMPO_CORRETO,
    MONTHNAME(ta2.change_time) AS MES,
    MONTH(ta2.change_time) AS NUMEROMES,
    t2.customer_id as EMPRESA
FROM 
    otrs.time_accounting ta2
    LEFT JOIN otrs.ticket t2 ON t2.id = ta2.ticket_id
    LEFT JOIN otrs.ticket_type as tt2 ON t2.type_id = tt2.id
    LEFT JOIN otrs.service as s2 ON t2.service_id = s2.id   
WHERE
    ta2.change_time between '2018-01-01' AND '2018-04-30' AND
    coalesce(t2.customer_id, 'ZSCHIMMER SCHWARZ') = 'ZSCHIMMER SCHWARZ' AND
    coalesce(tt2.name, 'CONTRATO PCH')            = 'CONTRATO PCH'
GROUP BY 
    MONTHNAME(ta2.change_time),
    MONTH(ta2.change_time),
    EMPRESA
ORDER BY 
    NUMEROMES

Try to use coalesce also, try to give one suitable for your case to see if it works.

    
21.05.2018 / 13:57