Как считать по месяцам с отношениями - PullRequest
0 голосов
/ 27 апреля 2020

Я сталкиваюсь с проблемой Доктрины / SQL! У меня есть объект Device и объект DeviceStatusHistory с отношением Many-to-Many.

Объект DeviceStatusHistory имеет 4 свойства: id, device, status, dateAdd .

Объект Device имеет: id, dateAdd, ...

Я хочу, чтобы каждые 12 прошедших месяцев УЧЕТ устройств по последнему состоянию (в последний день месяца).

Я пробовал несколько Mysql запросов в PhpMyAdmin, начиная со стороны DeviceStatusHistory' side or by Device`, но мне не удалось получить желаемый результат.

Я пытался, например:

SELECT COUNT(DISTINCT(dsh.device_id)) total_devices
     , dsh.status 
  FROM device_status_history dsh 
 WHERE dsh.status IN ('free', 'assigned', 'deployed', 'given_back', 'to_be_recycled', 'winterized', 'under_repair', 'at_after_sale') 
   AND dsh.date_add <= LAST_DAY(NOW())      
 GROUP 
    BY dsh.status

, он возвращает мне:

+---------------+--------------+
| total_devices |    status    |
+---------------+--------------+
|             1 | assigned     |
|          1585 | deployed     |
|            68 | free         |
|             2 | given_back   |
|             1 | under_repair |
+---------------+--------------+

Если я добавлю DeviceStatusHistory для 'развернутого' Device со статусом «Given_back», у меня должно быть

+---------------+--------------+
| total_devices |    status    |
+---------------+--------------+
|             1 | assigned     |
|          1584 | deployed     |
|            68 | free         |
|             3 | given_back   |
|             1 | under_repair |
+---------------+--------------+

Но это дает мне:

+---------------+--------------+
| total_devices |    status    |
+---------------+--------------+
|             1 | assigned     |
|          1585 | deployed     |
|            68 | free         |
|             3 | given_back   |
|             1 | under_repair |
+---------------+--------------+

Мы можем видеть, что мы посчитали устройство дважды, но я хочу посчитать его только один раз.

Как я могу добиться этого за последние 12 месяцев в SQL Quary или Doctrine запросе в Symfony

1 Ответ

0 голосов
/ 28 апреля 2020

Вот как бы я это сделал.

WITH last_12_month_EndIntervals AS 
(
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 1 MONTH) as StartInterval,LAST_DAY(NOW()) as EndInterval UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 2 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 1 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 3 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 2 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 4 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 3 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 5 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 4 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 6 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 5 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 7 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 6 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 8 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 7 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 9 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 8 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 10 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 9 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 11 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 10 MONTH) UNION ALL
SELECT DATE_SUB(LAST_DAY(NOW()), INTERVAL 12 MONTH),DATE_SUB(LAST_DAY(NOW()), INTERVAL 11 MONTH) 
), Lastest_Status_past_12_months AS (
select DISTINCT lst.StartInterval
    ,dsh.device_id
    ,LAST_VALUE(dsh.status) OVER (PARTITION BY lst.StartInterval,dsh.device_id 
                                    ORDER BY dsh.dateAdd ROWS BETWEEN UNBOUNDED PREECEDING 
                                    AND UNBOUNDED FOLLOWING) as LatestStatus
FROM last_12_month_EndIntervals lst
LEFT JOIN DeviceStatusHistory dsh ON (dsh.DateAdd > lst.StartInterval and dsh.DateAdd <= lst.EndInterval)
WHERE dsh.status IN ('free', 'assigned', 'deployed', 'given_back', 'to_be_recycled', 'winterized', 'under_repair', 'at_after_sale') 
)
SELECT StartInterval
    ,status
    ,COUNT(DISTINCT(device_id)) total_devices  
  FROM Lastest_Status_past_12_months  
GROUP BY StartInterval,status

Если у вас возникли проблемы, создайте ссылку dbfiddle со структурой таблицы и входными данными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...