在SQL中使用Group By on Date列

时间:2018-02-23 06:54:30

标签: sql vertica

我有大量的历史数据,我想按月分组。我正在准备下面的HP Vertica数据库查询,以按月分组我的数据。

SELECT 
      Region, Country,
      TO_TIMESTAMP(TO_CHAR(Order_Date,'m/yyyy'),'m/yyyy') as MONTH_Order_Date, 
      SUM(CAST(Unit_Price as NUMERIC(37,15))) as Sum_Unit_Price, 
      SUM(CAST(Total_Revenue as NUMERIC(37,15))) as Sum_Total_Revenue 
FROM SalesRecords 
GROUP BY Region,Country,TO_TIMESTAMP(TO_CHAR(Order_Date,'m/yyyy'),'m/yyyy')
ORDER BY Region ASC,Country ASC,TO_TIMESTAMP(TO_CHAR(Order_Date,'m/yyyy'),'m/yyyy') ASC

现在这个查询的问题是性能,超过10亿个数据需要花费近2分钟,并且分组后的返回记录设置为10万行。 我需要以下面显示的格式显示数据,因为我需要在数据库级别解析日期以获取格式化日期,这种格式在数据库服务器上花费时间。

请建议我可以使用的任何其他方式因为在同一个表上如果我在其他列上分组数据,除了日期类型列表现良好,返回记录设置几乎在40秒内超过10亿条记录。

我需要为所有主要的RDBMS执行此性能。

Region  Country     MONTH_Order_Date    Sum_Unit_Price          Sum_Total_Revenue
Asia    Bangladesh  2010-01-01 00:00:00 186252.349999999999937  920607119.140000001169023
Asia    Bangladesh  2011-01-01 00:00:00 186456.190000000000641  931633189.440000000452752
Asia    Bangladesh  2012-01-01 00:00:00 194925.550000000000312  969718040.969999998663069
Asia    Bangladesh  2013-01-01 00:00:00 194048.289999999999566  1017253078.219999998891571
Asia    Bangladesh  2014-01-01 00:00:00 184143.090000000000413  915867255.449999996567606
Asia    Bangladesh  2015-01-01 00:00:00 193697.769999999999864  959097995.869999999053554
Asia    Bangladesh  2016-01-01 00:00:00 184833.730000000000529  955360230.500000001682568
Asia    Bangladesh  2017-01-01 00:00:00 111476.840000000000014  563824376.189999998257226
Asia    Bhutan      2010-01-01 00:00:00 186506.900000000000474  916963415.479999997623498 

3 个答案:

答案 0 :(得分:1)

Vertica游程编码(RLE)允许您利用低基数列来提高查询性能和磁盘空间节省,并且将非常精细的数据类型(如时间戳)转换为mmyyyy可能非常适合这项工作。

1)将mmyyyy转换放入数据加载过程

2)使用名为month_year的新计算列创建一个新投影,并格式化为mmyyyy。

3)在投影列列表和投影ORDER BY中,将此卡和其他低卡列放在列表的开头。高卡列位于列表的末尾。但是任何高卡连接列(如密钥)应该紧跟在低卡列之后。

4)请务必在此卡和所有其他低卡列上指定ENCODING_RLE。

这两个指向Vertica文档的链接解释了所涉及的概念:

Choosing Sort Order: Best Practices

Optimizing Queries for Projections with Predicates

答案 1 :(得分:0)

按年份或月份分组,您可以使用:

GROUP BY YEAR(Order_Date)MONTH(Order_Date)

但是你的数据太大了,我们无法尝试在最后测试它,只有你可以进行实际的数学运算。

答案 2 :(得分:0)

我试试这个 - 每次改变都会加快一点,而这一切的总和可能会带来好的最终结果:

    SELECT
        Region
      , Country
      , YEAR(order_date)*100+month(order_date)   AS yearmonth
      -- extracting integers from dates is faster than TO_CHAR()
      -- and the result is INTEGER - the fastest type to GROUP BY ...
      , CAST(SUM(Unit_Price   ) AS NUMERIC(37, 15)) AS Sum_Unit_Price
      , CAST(SUM(Total_Revenue) AS NUMERIC(37, 15)) AS Sum_Total_Revenue
      -- instead of CAST-ing each input value, CAST the final grouping
      -- result once
    FROM SalesRecords
    GROUP BY 1,2,3 -- sometimes the optimizer is clever enough - 
    ORDER BY 1,2,3 -- but this ensures no repeated expression evaluation
    ;
祝你好运