MySQL从相关表中获取时间总计

时间:2010-03-17 18:16:25

标签: mysql

我们有一个订单簿和发票系统,我的任务是尝试从这些表中输出每月滚动总数。
但我不知道从哪里开始。我认为还有一些我甚至都不知道的SQL语法。我熟悉INNER / LEFT / JOINS和GROUP BY等,但按日期分组令人困惑,因为我不知道如何将数据限制为仅在当前分组的当前日期。我认为这将涉及将表格加入自己或可能是一个子选择。除了绝对必要之外,我一直认为最好避免使用子选择。

基本上系统有3个表
订单:order_id,currency,order_stamp
orders_lines:order_line_id,invoice_id,order_id,价格
发票:invoice_id,invoice_stamp
order_stamp和invoice_stamp是以整数存储的UTC unix时间戳,而不是MySQL时间戳。

我正在尝试按年/月显示当前未开单的订单总额(价格总和)。在该时间点。
当前订单是order_stamp在该月1日小于或等于00:00的订单 未开单的订单是invoice_stamp为null或invoice_stamp在该月的第1天大于00:00的订单。 在那个时间点,可能还没有相关的发票,invoice_id可能为空。

任何人都有任何关于我应该加入什么以及我需要分组的建议?

干杯,B

2 个答案:

答案 0 :(得分:0)

SELECT  yr, mon, COALESCE(SUM(price), 0)
FROM    (
        SELECT  2010 AS yr
        UNION ALL
        SELECT  2009
        UNION ALL
        …
        ) as years
CROSS JOIN
        (
        SELECT  1 AS mon
        UNION ALL
        SELECT  2
        …
        UNION ALL
        SELECT  12
        ) as months
LEFT JOIN
        orders o
ON      o.order_stamp <= UNIX_TIMESTAMP(CAST(CONCAT(year, mon, '01') AS DATE))
LEFT JOIN
        order_lines ol
ON      ol.order_id = o.order_id
        AND NOT EXISTS
        (
        SELECT  NULL
        FROM    invoice i
        WHERE   i.invoice_id = ol.invoice_id
                AND i.invoice_stamp > UNIX_TIMESTAMP(CAST(CONCAT(year, mon, '01') AS DATE))
        )
GROUP BY
        yr, mon

答案 1 :(得分:0)

架构中的日期让我感到困惑......订单标记是订单的UTC,对吧?而invoice_stamp是客户开票时的UTC吗?

我不确定你的“滚动月总数”是什么意思,所以我会假设这是一个月内所有发票的集合?并列出给定月份的所有订单?

未开单的客户是那些没有发票的客户......

如果是这样的话,那就像:

   SELECT YEAR(FROM_UNIXTIME(order_stamp)), 
          MONTH(FROM_UNIXTIME(order_stamp)), 
          SUM(price)
   FROM orders
      LEFT JOIN order_lines USING (order_id)
      LEFT JOIN invoices USING (invoice_id)
   WHERE invoices.invoice_id IS NULL
   GROUP BY YEAR(FROM_UNIXTIME(order_stamp)), 
            MONTH(FROM_UNIXTIME(order_stamp))

......应该让你到那儿。

如果您正在寻找超过30天的东西的收集成本,您需要以下内容:

SELECT YEAR(FROM_UNIXTIME(invoice_date)), 
       MONTH(FROM_UNIXTIME(invoice_date)), 
       SUM(OverThirtyDayPrice),
       AVG(CollectionDays)
FROM 
    (
     SELECT invoice_date,
            IF(
               DATEDIFF(
                        FROM_UNIXTIME(IFNULL(invoice_stamp, UNIX_TIMESTAMP()), 
                        order_stamp) > 30, 
               price, 
               0
              ) AS OverThirtyDayPrice,
            DATEDIFF(FROM_UNIXTIME(IFNULL(invoice_stamp, UNIX_TIMESTAMP()),
                     order_stamp)) AS CollectionDays
     FROM orders
         LEFT JOIN order_lines USING (order_id)
         LEFT JOIN invoices USING (invoice_id)
    )
GROUP BY YEAR(FROM_UNIXTIME(invoice_date)), 
         MONTH(FROM_UNIXTIME(invoice_date))

我们可以稍微破解最后一个,以使其适用于一个月内订购的产品,但在另一个产品中收费:

SELECT YEAR(invoice_datetime), 
       MONTH(invoice_datetime), 
       SUM(OutOfMonthPrice)
FROM 
    (
     SELECT FROM_UNIXTIME(IFNULL(invoice_stamp, UNIX_TIMESTAMP())) AS invoice_datetime,
            IF(MONTH(
                     FROM_UNIXTIME(IFNULL(invoice_stamp, UNIX_TIMESTAMP()))
                    ) 
               <> 
               MONTH(FROM_UNIXTIME(order_stamp)),
               price, 
               0
              ) AS OutOfMonthPrice,
     FROM orders
         LEFT JOIN order_lines USING (order_id)
         LEFT JOIN invoices USING (invoice_id)
    )
GROUP BY MONTH(invoice_datetime), YEAR(invoice_datetime)

如果您想获得“时间点”查询,您可能会发现RDBMS不是您需要的东西(您需要迭代一系列查询,每个查询都针对特定的月/年)和/或您的基本设计不支持您尝试生成的报告。

理想情况下,您想要的是存档和报告的月度报告。