我有一个查询,其中我获得了属于特定日期范围的记录的总和。现在我想在每个日期范围内包含一列的最新日期。
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个单独的表格中。
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
答案 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中)。更重要的是,它们阻止使用索引来优化查询。