mysql: упростить группировку запросов по нескольким полям

#mysql #sql #select #group-by #multiple-columns

#mysql #sql #выберите #группировка по #несколько столбцов

Вопрос:

У меня есть таблица:

 date, number, flag1, flag2, flag3
2015, 10,     1,    NULL, NULL
2015, 10,     1,    NULL, NULL
2015, 10,     0,    NULL, NULL
2015, 11,     1,    NULL,    NULL
2015, 11,     NULL, 1,    NULL
2015, 11,     NULL, 0,    NULL
2015, 12,     NULL, NULL, 0
2016, 10,     1,    NULL, NULL
2016, 11,     0,    NULL, NULL
2016, 13,     NULL, 1,    NULL
2016, 13,     NULL, NULL, 1
2016, 13,     NULL, NULL, 1
2016, 13,     NULL, NULL, 1
  

(NULL = 0)

Мне нужно получить группировку данных по дате:

 date, flag1, flag2, flag3
2015, 2,     1      0
2016, 1,     1,     1
  

Подробнее:

Для каждой даты необходимо подсчитать количество флагов1, флаг2, флаг3, флаг которых = 1 и столько же

например, для flag1:

 number = 10, flag1 = 1
number = 10, flag1 = 0
number = 10, flag1 = 1
number = 10, flag1 = 1
  

будет считаться = 1

 number = 10, flag1 = 1
number = 10, flag1 = 0
number = 11, flag1 = 1
number = 11, flag1 = 1
  

будет считаться = 2

 number = 10, flag1 = 0
number = 10, flag1 = 0
number = 11, flag1 = 1
number = 11, flag1 = 1
  

будет считаться = 1

A написал предупреждающий sql-код, но это сложно, медленно и т. Д

 SELECT
    date,
    SUM(count1) AS count1,
    SUM(count2) AS count2,
    SUM(count3) AS count3
FROM
(
    SELECT
        date,
        IF(SUM(flag1) <> 0, 1, 0) AS count1,
        IF(SUM(flag2) <> 0, 1, 0) AS count2,
        IF(SUM(flag3) <> 0, 1, 0) AS count3
    FROM
        table
--  WHERE
    GROUP BY
        number
) AS tmp
GROUP BY
    date
ORDER BY
    date;
  

Подскажите, можно ли упростить и ускорить код


Упрощенный

 SELECT
    date,
    SUM(count1) AS count1,
    SUM(count2) AS count2,
    SUM(count3) AS count3
FROM
(
    SELECT
        date,
        COUNT(DISTINCT(flag1)) AS count1,
        COUNT(DISTINCT(flag2)) AS count2,
        COUNT(DISTINCT(flag3)) AS count3
    FROM
        table
--  WHERE
    GROUP BY
        object_id
) AS tmp
GROUP BY
    date
ORDER BY
    date;  
  

Комментарии:

1. Что, если есть четвертый флаг?

Ответ №1:

Вариант вашего исходного запроса:

 SELECT `date`, 
       SUM(flag1=1) AS flag1,
       SUM(flag2=1) AS flag2,
       SUM(flag3=1) AS flag3
FROM (
   SELECT `date`, 
          MAX(flag1) AS flag1, 
          MAX(flag2) AS flag2,
          MAX(flag3) AS flag3
   FROM mytable
   GROUP BY `date`, number) AS t
GROUP BY `date`   
ORDER BY `date`
  

Вы можете попробовать это и посмотреть, как это сравнивается с другим запросом.

Демонстрация здесь

Комментарии:

1. Упрощенный ВЫБОР даты, СУММЫ (count1) КАК count1, SUM(count2) КАК count2, СУММА (count3) КАК count3 ИЗ (ВЫБЕРИТЕ дату, COUNT(DISTINCT(флаг1)) КАК count1, COUNT(DISTINCT(флаг2)) КАК count2, COUNT(DISTINCT(флаг3)) КАК count3 ИЗ таблицы — ГДЕ ГРУППА ПО object_id ) КАК tmp ГРУППА ПО дате ПОРЯДОК ПО дате;

Ответ №2:

Я предлагаю вам реструктурировать вашу таблицу примерно так:

 date, number, flag_no, flag_value
2015,     10,       1,          1
2015,     10,       1,          1
2015,     10,       1,          0
2015,     11,       1,          1
2016,     10,       1,          1
2016,     11,       1,          0
2015,     11,       2,          1
2015,     11,       2,          0
2016,     13,       2,          1
2015,     12,       3,          0
2016,     13,       3,          1
2016,     13,       3,          1
2016,     13,       3,          1