我无法让MySQL正确地返回查询。
这是我的数据:
id date value
2 2011-01-04 55.66
2 2011-03-23 22.33
2 2011-04-21 9.44
5 2010-01-04 104.55
5 2011-02-03 38.82
... ... ...
我正在尝试返回一个查询:
select t1.id, max(t1.date), t1.value, t2.id, min(t2.date), t2.value
from tab1 as t1, tab1 as t2
where t1.id = t2.id
and t1.date <= '2011-03-31'
and t2.date >= '2011-04-01'
group by t1.id;
但这是永远的(db有~1mm线)。我尝试了各种连接但是它似乎忽略了日期&lt;和&gt;声明。基本上我希望每个客户在2011年4月1日之前的最后购买日期和金额以及他们在2011年4月1日或之后的首次购买和日期。任何建议都会很棒。
答案 0 :(得分:1)
SELECT t2.*
FROM tab1 t2
INNER JOIN
(SELECT t1.id,
MIN(CASE WHEN t1.date>='2011-04-01' THEN t1.date END) as min_date_1,
MAX(CASE WHEN t1.date<='2011-03-31' THEN t1.date END) as max_date_2
SUM(CASE WHEN t1.date>='2011-04-01' THEN t1.value END) sum_1,
SUM(CASE WHEN WHEN t1.date<='2011-03-31' THEN t1.value END) sum_2
FROM tab1 t1
GROUP BY t1.id)a ON
(a.id = t2.id AND (t2.date = a.min_date_1 OR t2.date = a.max_date_2))
假设您有索引(id,date),它应该可以很快地工作。
更新添加总和
答案 1 :(得分:1)
您的查询存在缺陷,列t1.value和max(t1.date)与one和other之间没有关系。
如果您想知道所选日期的总购买量,您需要按如下方式重写。
SELECT st1.id, st1.date, st1.total_value, st2.id, st2.date, st2.total_value
FROM (SELECT t1.id, t1.date, sum(t1.value) as total_value
FROM tab1 t1
WHERE t1.date <= '2011-03-31'
GROUP BY t1.id
HAVING t1.date = MAX(t1.date)
) st1
INNER JOIN (SELECT t2.id, t2.date, sum(t2.value) as total_value
FROM tab1 t2
WHERE t2.date > '2011-03-31'
GROUP BY t2.id
HAVING t2.date = MAX(t2.date)
) st2
ON (st1.id = st2.id)
确保您在id
和date
<强>说明强>
id
通常被理解为主键的简写
有一个名为id
的字段不一个唯一索引,令人困惑,并被广泛认为是代码气味。
答案 2 :(得分:1)
SELECT
td.id
, ta.`date` AS before_date
, ta.value AS value_at_before_date
, tb.`date` AS after_date
, tb.value AS value_at_after_date
FROM
( SELECT DISTINCT id
FROM tabl
) AS td
LEFT JOIN
tabl AS ta
ON ta.tablePK =
( SELECT tablePK
FROM tabl AS a
WHERE `date` < '2011-04-01'
AND a.id = td.id
ORDER BY `date` DESC
LIMIT 1
)
LEFT JOIN
tabl AS tb
ON tb.tablePK =
( SELECT tablePK
FROM tabl AS b
WHERE `date` >= '2011-04-01'
AND b.id = td.id
ORDER BY `date` ASC
LIMIT 1
)
其中tablePK
是表格的PRIMARY KEY
(我希望你有一个)。
(id, date, tablePK)
上的索引对速度有帮助。
答案 3 :(得分:1)
数据 - 查询生成一些测试数据,而不是创建表保持测试数据。
before_query - 检索每个客户ID的最长日期&lt; = 2011-03-31
after_query - 为每个客户ID检索最小日期&gt; = 2011-04-01
除了使用Oracle的虚拟dual
表(我用它来生成一些测试数据)之外,我相信我只使用了标准的SQL语法。
您不需要生成数据,因此可以省略部分查询。在查询中引用data
的任何地方,请将其替换为table name
。
with
data as (select 2 as id, '2011-01-04' as trans_date, 55.66 as value from dual
union all
select 2 as id, '2011-03-23' as trans_date, 22.33 as value from dual
union all
select 2 as id, '2011-04-21' as trans_date, 9.44 as value from dual
union all
select 5 as id, '2010-01-04' as trans_date, 104.55 as value from dual
union all
select 5 as id, '2011-02-03' as trans_date, 38.82 as value from dual),
before_qry as (select id, max(trans_date) as max_date from data
where trans_date <= '2011-03-31'
group by id),
after_qry as (select id, min(trans_date) as min_date from data
where trans_date >= '2011-04-01'
group by id)
select bq.*, bq_d.value, aq.*, aq_d.value
from before_qry bq inner join after_qry aq on bq.id = aq.id
inner join data bq_d on bq.id = bq_d.id and bq.max_date = bq_d.trans_date
inner join data aq_d on aq.id=aq_d.id and aq.min_date = aq_d.trans_date
对于您的问题中显示的测试数据,此查询提供以下结果
ID MAX_DATE VALUE ID MIN_DATE VALUE
---------- ---------- ---------- ---------- ---------- ----------
2 2011-03-23 22.33 2 2011-04-21 9.44