如何编写带有两个按组分组的SQL select,还包括缺少日期的月份

时间:2017-11-02 02:57:53

标签: sql select group-by

我有一张汽车表,基本上包括所有销售清单。表格如下:

carType, soldDate, price

我想生成一个显示每个月总计的结果,包括没有条目(没有销售额)的月份,按月份和年份分组,但也按carType分组。我有以下SQL查询,但我似乎无法弄清楚如何包含所有缺少的月份:

 SELECT 
        carType, YEAR(date) AS year, MONTH(date) as month,  SUM(amount)
    FROM
        cars
    GROUP BY 
        YEAR(date), MONTH(date), carType
    ORDER by    
        carType, year, month

我还想运行查询,没有设置开始和结束日期以及指定的开始和日期(如在两个不同的查询中)。任何有关如何做到这一点的帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

一种解决方案是使用包含所有年份和月份的期间的表格。

然后,使用查询结果进行外部联接。

答案 1 :(得分:0)

这是不可能的。根据JeffRichards对这个问题的评论,如果数据不存在,那就不存在了。您可以尝试在另一个临时表(可能非常复杂)中预先填充它以及许多其他可能的选项,但Jeff所说的最佳解决方案实际上是在另一层编写它。这就是我所做的,而且代码非常易于管理。

如果您在Java中执行此操作,则可以使用以下代码创建所需月份和年份的列表:

// You could also .map() it to YearMonth instead of LocalDate's
// The plusMonths(1) is import so that it includes the last month
List<LocalDate> allMonths = Stream.iterate(startDate, date -> date.plusMonths(1))
        .limit(ChronoUnit.MONTHS.between(startDate, endDate.plusMonths(1)))
        .collect(Collectors.toList());

然后,您将浏览SQL生成列表并添加任何缺失的月份:

allMonths.stream()
    .forEach(date ->
    {
        totalCarList.stream()
            .filter(car -> isSameMonthAndYear(car.getTotal().getDate, date))
            .findAny()
            .orElseGet(() ->
            {
                totalCarList.add(new Total(date, 0.00))
            });
    });

最后,您只需按日期对列表进行重新排序:

totalCarList.sort(Comparator.comparing(Total::getDate));

当然有不同的方法,但是它的复杂程度要小得多,然后尝试将其推入SQL层,而SQL层用于处理现有数据,而不是试图将数据推送到不存在的地方。前...