MySQL查询 - 使用自联接查找最接近开始和结束日期的行

时间:2017-09-20 14:41:52

标签: mysql mariadb

我有以下查询使用一个表来查找最接近日期范围任一端的帐号列表的revenue列,即最接近日期范围开头的行,以及最接近结束的那个。

我想出了以下内容,但它似乎只适用于第一个帐号而不是其他任何帐号。

SELECT a.acct_no,
b.revenue AS first_value, b.created_at AS first_date,
c.revenue AS second_value, c.created_at AS second_date

FROM `revenue_figures` a

LEFT JOIN (
    SELECT `acct_no`, `revenue`, `created_at`
    FROM  `revenue_figures`
    WHERE `created_at` BETWEEN '2017-02-28 00:00:00' AND '2017-03-31 23:59:59'
    AND `acct_no` IN ('A123', 'A124')
    GROUP BY `acct_no`, `revenue`, `created_at`
    ORDER BY `created_at` ASC
    LIMIT 1
) b ON a.acct_no = b.acct_no

LEFT JOIN (
    SELECT `acct_no`, `revenue`, `created_at`
    FROM  `revenue_figures`
    WHERE `created_at` BETWEEN '2017-02-28 00:00:00' AND '2017-03-31 23:59:59'
    AND `acct_no` IN ('A123', 'A124')
    GROUP BY `acct_no`, `revenue`, `created_at`
    ORDER BY `created_at` DESC
    LIMIT 1
) c ON a.acct_no = c.acct_no

WHERE a.`created_at` BETWEEN '2017-02-28 00:00:00' AND '2017-03-31 
23:59:59'
AND a.`acct_no` IN ('A123', 'A124')

GROUP BY a.acct_no, first_value, first_date, second_value, second_date

这会生成以下内容,但表中有A124帐号的数字:

acct_no first_value first_date  second_value    second_date
A123    8990.00     2017-02-28  7364.80         2017-03-31 01:00:00
A124    NULL        NULL        NULL            NULL

我认为查询存在一个根本性的缺陷,因为我注意到如果我运行它几次,我可以生成不同的结果,例如:

acct_no first_value first_date  second_value    second_date
A123    8990.00     2017-02-28  NULL            NULL
A124    NULL        NULL        28361.76        2017-03-31 01:00:00

表格结构

id, acct_no, revenue, created_at

示例数据

1, A123, 8990.00, 2017-02-28 01:00:00
2, A123, 7364.80, 2017-03-31 01:00:00
3, A124, 17324.12, 2017-02-28 01:00:00
4, A124, 28361.76, 2017-03-31 01:00:00

1 个答案:

答案 0 :(得分:1)

(重新开放是因为OP的代码处理了所讨论的“dup”问题。真正的问题是关于另一个问题。)

问题是你要求最新的两个acct_nos,然后LIMIT 1,它会抛出其中一个。UNION ALL。让我们首先关注一个子查询。

我说你想要2行,每个acct_no一个,我是否正确?为此,您需要为每个acct_no查找1行。并且可能唯一的方法是SELECT ... ORDER BY ... LIMIT 1两个GROUP BY。否LEFT JOIN ( ( SELECT ... acct_no = 'A123' ... LIMIT 1 ) UNION ALL ( SELECT ... acct_no = 'A124' ... LIMIT 1 ) )

所以,现在你有了

LEFT JOIN

首先首次亮相UNION以查看它是否获得了所需的一对行。

然后将它放入每个LEFT(虽然我不知道你是否需要INDEX(acct_no, created_at) )以查看大查询是否正常。

其他一些提示......

    created_at >= '2017-03-01'
AND created_at  < '2017-03-01' + INTERVAL 1 MONTH

使用此模式:

created_at

你所拥有的包括2月的最后一天,以及3月的全部;这是故意的吗?并且,DATETIMEGROUP BY吗?还是其他一些数据类型?

外部 GROUP BY acct_no 应该只是

<div class="share"></div>