查询销售额,按周分组

Querying sales, grouped by weeks

我正在尝试在 SQLLite 中为我的应用组合一个查询,想寻求一点帮助。

我要写的查询:

“我是用户 ID x 的用户。对于我的个人工作周,可以在我想要的任何一天 D 开始(周日到周六,周一到周日等),我想看看哪一天就销售额而言,工作周是我最差的一周,但也是我最好的一周。

为简单起见,"worst" 和 "best" 仅表示该周最高和最低销售额的总和。

如果每个人的工作周都从周日开始,这很容易,但事实并非如此。我必须克服 SQL 挑战,将数据库中的所有行分组 table 不仅按周,而且按自定义周(用户定义一周的开始和结束日期)。

例如,如果我的工作周从星期日开始,那么在过去的一周中,5 月 28 日那一周是星期日,并且是我工作周的开始(到 6 月 3 日这个星期六结束)。我将对 table.

中的所有记录遵循此模式

但是,不同的用户可以让他们的工作周从 5 月 29 日星期一开始,到 6 月 2 日星期五结束。

所以这意味着对于用户 1,我想从星期日的开始日到星期六的结束日对他的行进行分组(然后将它们全部汇总,并获取第一个和最后一个销售记录) .

但是,对于用户 2,我想将他的记录分组在周一到周日的日期范围内

这是我目前所处的位置。我想我很接近。

(请注意,我将日期存储为以毫秒为单位的 unix 时间戳,因此除以 1000 和 unixepoch 部分)。 +d 部分实际上是一个基于一天开始的整数,但我还没有弄清楚这个数字到底应该是多少。就在我以为我明白了的时候,它却在别人的日子里失败了。

SELECT 'Date', SUM(Amount) 'Amount'  
FROM Sales WHERE UserID = x
GROUP BY CAST(( julianday((datetime(CreationDate / 1000, 'unixepoch', 'localtime')) + d) / 7 ) AS INT) 

有没有人认为他们可以帮助我? :)

非常感谢!

编辑

非常感谢您的帮助!

对于+d的问题('d'的值应该抵消多少)? 这是我在测试后发现的,据我所知这是有效的。我知道 Sqllite 使用 0 作为星期日,1 作为星期一,等等,我知道我们正在分组并除以 7(一周中的 7 天),但不知道为什么这些是 'd' 的正确值偏移量?它现在似乎正在工作。我看到模式变成了 2,1,0,6,5,4,3 但是有点奇怪的顺序是吗?

if (day == Sunday) //if your work week starts on Sunday, d=2
     return 2
else if (day == Monday)
     return 1
else if (day == Tuesday)
     return 0
else if (day == Wednesday) 
     return 6
else if (day == Thursday) 
     return 5
else if (day == Friday) 
     return 4
else if (day == Saturday) 
     return 3

请尝试执行以下查询:

select 
  min(to_char(to_date(order_date,'mm/dd/yyyy'),'Day'))
    keep(dense_rank first order by sum(sales) desc) best_day,
  min(to_char(to_date(order_date,'mm/dd/yyyy'),'Day'))
    keep(dense_rank last order by sum(sales) desc)worst_day
from orders
where userid=x
group by to_char(to_date(order_date,'mm/dd/yyyy'),'Day');

你们很亲近。

  1. 您正在将 d 添加到日期时间。我不知道这是否真的增加了天数。如果在 SQLite 中将整数添加到日期时间,我无法弄清楚会发生什么。要保存它,请将这一天添加到儒略日。您不必先获取日期时间,顺便说一句,从这个儒略日开始,您可以一步完成:

    julianday(CreationDate / 1000, 'unixepoch', 'localtime') + d
    

    这是我在您的查询中看到的唯一真正的缺陷。

  2. 儒略日是小数,例如 2457907.5。当您调用带有 / 的除法时,您会得到一个小数结果。我看到您将此结果转换为 INT,但我建议先转换为 INT,然后再进行除法,这样会隐含地成为整数除法。

    cast(julianday(CreationDate / 1000, 'unixepoch', 'localtime') + d as int) / 7

    这只是为了便于阅读;我得到一个天数(2457907 而不是某个小数点 2457907.5)和整数除以 7(例如 2457907 / 7 = 351129)。

整个查询:

SELECT 
  MIN(DATE(CreationDate / 1000, 'unixepoch', 'localtime')) AS from_date, 
  MAX(DATE(CreationDate / 1000, 'unixepoch', 'localtime')) AS till_date, 
  SUM(Amount) AS total
FROM Sales 
WHERE UserID = x
GROUP BY CAST(JULIANDAY(CreationDate / 1000, 'unixepoch', 'localtime') + d as INT) / 7
ORDER BY SUM(Amount);

from_datetill_date 并不总是代表完整的 7 天,而是只代表工作日(例如从周日到周六的一周,但只在周一、周三和周五工作,它将显示星期一和星期五的日期)。显示真实的一周需要做更多的工作。 (我现在最好不要尝试这个,因为很容易请假一天,而无法尝试查询。)

编辑: 这是我对每周开始和结束日期的尝试。当我们对浮点值调用 DATE 时,该值被认为是儒略日。 (也许它也适用于整数,我无法从文档中确定。)

SELECT 
  DATE(CAST(CAST(JULIANDAY(CreationDate / 1000, 'unixepoch', 'localtime') + d as INT) / 7 as REAL)) AS from_date,
  DATE(CAST(CAST(JULIANDAY(CreationDate / 1000, 'unixepoch', 'localtime') + d as INT) / 7 as REAL), '+6 day') AS till_date,
  MIN(DATE(CreationDate / 1000, 'unixepoch', 'localtime')) AS first_working_day, 
  MAX(DATE(CreationDate / 1000, 'unixepoch', 'localtime')) AS last_working_day, 
  SUM(Amount) AS total
FROM Sales 
WHERE UserID = x
GROUP BY CAST(JULIANDAY(CreationDate / 1000, 'unixepoch', 'localtime') + d as INT) / 7
ORDER BY SUM(Amount);