从2个表格和指定日期之间选择最新日期

时间:2015-10-09 10:25:53

标签: mysql sql

我有一个查询,其中我获得了属于特定日期范围的记录的总和。现在我想在每个日期范围内包含一列的最新日期。

SQL小提琴:

http://sqlfiddle.com/#!9/2b486/6

查询:

SELECT
Contract.contract_length,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-01-01 00:00:00' AND '2013-03-31 23:59:59'
  THEN 1 ELSE 0 END
) as rental_count_Q1_2013,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-01-01 00:00:00' AND '2013-03-31 23:59:59'
    AND termination_date BETWEEN '2013-01-01 00:00:00' AND NOW()
  THEN 1 ELSE 0 END
) as terminated_count_Q1_2013,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-01-01 00:00:00' AND '2013-03-31 23:59:59'
    AND(
      Data1Payout.payout_date BETWEEN '2013-01-01 00:00:00' AND NOW()
      OR Data2Payout.payout_date BETWEEN '2013-01-01 00:00:00' AND NOW()
    )
  THEN 1 ELSE 0 END
) as customer_payouts_Q1_2013,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-04-01 00:00:00' AND '2013-06-30 23:59:59'
  THEN 1 ELSE 0 END
) as rental_count_Q2_2013,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-04-01 00:00:00' AND '2013-06-30 23:59:59'
    AND termination_date BETWEEN '2013-04-01 00:00:00' AND NOW()
  THEN 1 ELSE 0 END
) as terminated_count_Q2_2013,
SUM(
  CASE WHEN
    Contract.created BETWEEN '2013-04-01 00:00:00' AND '2013-06-30 23:59:59'
    AND(
      Data1Payout.payout_date BETWEEN '2013-04-01 00:00:00' AND NOW()
      OR Data2Payout.payout_date BETWEEN '2013-04-01 00:00:00' AND NOW()
    )
  THEN 1 ELSE 0 END
) as customer_payouts_Q2_2013

FROM contracts AS Contract
LEFT OUTER JOIN (
  SELECT id, customer_id, payments_made, termination_date FROM terminations
) AS Termination on Termination.customer_id = Contract.customer_id
LEFT OUTER JOIN (
  SELECT id, customer_id, payout_date FROM datasource_1_payouts
) AS Data1Payout on Data1Payout.customer_id = Contract.customer_id
LEFT OUTER JOIN (
  SELECT id, customer_id, payout_date FROM datasource_2_payouts
) AS Data2Payout on Data2Payout.customer_id = Contract.customer_id
GROUP BY Contract.contract_length

这将返回每个季度的租金,租金终止和这些租金的支出,并按合同期限分组。

contract_length | rental_count_Q1_2013 | terminated_count_Q1_2013 | customer_payouts_Q1_2013 | rental_count_Q2_2013 | terminated_count_Q2_2013 | customer_payouts_Q2_2013
24              |           2          |           1              |           1              |           1          |           0              |           1
36              |           2          |           1              |           1              |           2          |           0              |           2
48              |           1          |           1              |           0              |           2          |           1              |           1

我还需要获得每个季度的最后一次付款日期。 I.E.最后一次付款是根据2013年第一季度创建的合同进行的。付款也存储在2个单独的表格中。

我尝试过:

使用MAX():

CASE WHEN
    Contract.created BETWEEN '2013-01-01 00:00:00' AND '2013-03-31 23:59:59'
    AND Data1Payout.payout_date BETWEEN '2013-04-01 00:00:00' AND NOW()
    AND MAX(Data1Payout.payout_date) > MAX(Data2Payout.payout_date)
    THEN MAX(Data1Payout.payout_date) ELSE MAX(Data2Payout.payout_date) END
as last_payout_date_Q1_2013

这不起作用,因为所有支付日期都包含在每个结果中,因此MAX()始终是最新的。

工作解决方案:

MAX(
    CASE WHEN Contract.created BETWEEN '2013-01-01 00:00:00' AND '2013-03-31 23:59:59'
    THEN GREATEST(IFNULL(Data1Payout.payout_date, '0000-00-00'), IFNULL(Data2Payout.payout_date, '0000-00-00'))
    ELSE NULL END
) AS last_payout_date_Q1_2013

2 个答案:

答案 0 :(得分:1)

您将MAX功能放在错误的位置。实际上,它与其他 CASE语句相同 由于你的查询太长,我会给出一个简单的解释,我希望这会帮助你。

SELECT 
    SUM(
    CASE WHEN x = 'yes'
    THEN 1 ELSE 0
    END) AS SUM_NUMBER, --terminated_count_Q1_2013 for example
    MAX(
    CASE WHEN x = 'yes'
    THEN yourdatecolumn
    ELSE NULL END) AS MAX_DATE --last_payout_date_Q1_2013 for example
FROM yourtable

我希望您知道如何在您自己的查询中实现此功能。

答案 1 :(得分:1)

MySQL提供了一种简化现有查询的好方法。例如,第一个值可以计算为:

SELECT Contract.contract_length,
       MAX(CASE WHEN Contract.created >= '2013-01-01' AND contract.created < '2013-04-01'
                THEN Contract.created
          ) as rental_count_Q1_DATE,

您的问题不明确哪个列要最大化。但是,您可以使用相同的想法:

<

请注意,我将日期逻辑更改为仅使用天数(在第二个日期使用严格between)。我认为这比FROM更安全(也更容易阅读)。无论列是否具有时间组件,此逻辑都有效。而且,它适用于一天中的所有时间。

此外,您不应在click子句中使用子查询,除非您需要,而且您不需要。实现它们的开销(仅在MySQL中)。更重要的是,它们阻止使用索引来优化查询。