2016-12-20 2 views
0

Я пытаюсь запросить таблицу postgres db для подсчета строк, соответствующих некоторым критериям между временным диапазоном. Я использую sequelize orm с nodejs. В моем методе контроллера У меня есть запросПодсчет количества критериев соответствия строк между двумя датами

var query = 'SELECT o.ordered_at, COUNT(o.id) AS order_count FROM "Orders" o WHERE status = :status AND o.ordered_at >= :lower_limit AND o.ordered_at <= :upper_limit GROUP BY o.id ORDER BY o.ordered_at DESC'; 

     models.sequelize.query(query, queryOptions). 
     then(function (orders) { 
     res.status(200).json(response); 
     }). 
     catch(function (err) { 
     logger.error(err); 
     res.status(500).json(err.message); 
     }) 

это дает ответ, как этот

[ 
    { 
    "ordered_at": "2016-12-10T16:05:46.525Z", 
    "order_count": "1" 
    }, 
    { 
    "ordered_at": "2016-12-10T16:03:46.429Z", 
    "order_count": "1" 
    }, 
    { 
    "ordered_at": "2016-12-10T16:01:46.440Z", 
    "order_count": "1" 
    }, 
    { 
    "ordered_at": "2016-12-05T12:20:18.714Z", 
    "order_count": "1" 
    }, 
    { 
    "ordered_at": "2016-12-05T12:18:18.650Z", 
    "order_count": "1" 
    }, 
    { 
    "ordered_at": "2016-12-03T12:16:18.658Z", 
    "order_count": "1" 
    } 
] 

Вы можете увидеть запрос возвращает order_count для каждой строки, а не для каждого заказа, поэтому я стараюсь для преобразования данных здесь

var data = [], 
     lower_time_limit = t(new Date()); 

    var range = _.range(30), 
     month_lower_limit = t(lower_time_limit).subtract(1, 'M').startOf('day'); 

    var lower_limit, 
     limit, 
     upper_limit; 

    _.forEach(range, function (day, key) { 
     limit = t(month_lower_limit); 
     lower_limit = t(limit.add(day, 'd')); 
     upper_limit = t(limit.add(1, 'd')); 

     _.forEach(orders, function (order, index) { 
     var count = 0; 
     if (t(order.ordered_at).isBetween(lower_limit, upper_limit, 'second', '[)')) { 
      var orderCount = count + parseInt(order.order_count); 
      data.push({date: lower_limit, count: orderCount}) 
     } 
     }); 
    }); 

    return data; 

Я знаю, что чего-то не хватает, просто не могу понять это.

+1

То, что вы хотите, не ясно, но, похоже, она может и должна быть простая задача SQL, которая не должна быть исправлена ​​путем постобработки, но с правильный SQL-запрос. –

+0

@ DenysSéguret Я пытаюсь получить количество строк, которые имеют определенное значение для поля состояния и лежат между двумя датами. Мой запрос дает мне счет для каждой строки, а не каждый день, поэтому я пытаюсь выполнить постобработку результата и агрегировать данные за каждый день, а затем каждый час в зависимости от диапазона дат. – MrFoh

ответ

0

GROUP BY o.id будет производить одну группу (то есть одну строку на выходе) за o.id. Вам нужна одна группа для всех совпадающих строк, что вы получаете, если полностью опустить GROUP BY.

Включая o.ordered_at в ваш выход не имеет большого смысла; если вы объединяете несколько совпадающих строк в одну выходную запись, неясно, чье ordered_at время, которое вы ожидаете увидеть.

И как только у вас есть один ряд выходов, ORDER BY не принесет вам много пользы.

С учетом всего этого в виду:

SELECT COUNT(o.id) AS order_count 
FROM "Orders" o 
WHERE status = :status 
    AND o.ordered_at >= :lower_limit 
    AND o.ordered_at <= :upper_limit