我试图查询数据库以找到与我传入的参数最接近的日期。
我遇到了一个问题,我已经在IRC和列表中工作了一段时间,但无法找到解决方案。我使用python DBAPI(sqlalchemy)并通过CLI和Flask App访问数据(但这不应该影响SQL)。该数据库是带有InnoDB引擎的MySQL。
查询将取决于名为target_expiration
的因子,但该值通常不存在于DB中。我需要找到哪个值最接近。例如,我会传递target_date='2015-06-02'
并希望它返回给我2015-06-03
结果和距我2015-06-01
一天的target_date
结果。
尝试解决方案:
SELECT * FROM table1 HAVING MIN(ABS(DATEDIFF(table1.Expiration,
'2015-06-02'))) = ABS(DATEDIFF(table1.Expiration, '2015-06-02'));
这不返回任何行。我可以运行相同的MIN(ABS(DATEDIFF(...)))
来返回scalar()
并成功并打印一个值。
我尝试使用HAVING
函数来使用聚合函数。我正在寻找扫描数据库并找出我最接近目标日期的截止日期。如果它为零,我已经完成了 - 我找到了日期,然后我只想返回所有匹配的日期。如果它是一天之后,我不知道它是向前还是向后退一天(我将处理添加更多功能以便稍后选择,但是现在我和#39; d只想返回n
天之前或之后的所有值。
示例数据: table1
这是一个极其有限的数据样本,实际上我有大约40列和数十亿行,所以速度是一个因素。
+------------+-------------+-------+
| Expiration | ProductType | Price |
+------------+-------------+-------+
| 2015-06-01 | 2 | 25 |
+------------+-------------+-------+
| 2015-06-03 | 1 | 22 |
+------------+-------------+-------+
| 2015-05-28 | 1 | 22 |
+------------+-------------+-------+
| 2015-05-28 | 2 | 28 |
+------------+-------------+-------+
| 2015-05-28 | 1 | 22 |
+------------+-------------+-------+
| 2015-06-04 | 2 | 28 |
+------------+-------------+-------+
| 2015-05-25 | 1 | 22 |
+------------+-------------+-------+
| 2015-05-25 | 2 | 28 |
+------------+-------------+-------+
答案 0 :(得分:1)
单个结果:
SELECT *
FROM table1
ORDER BY ABS(DATEDIFF(table1.Expiration, '2015-06-02')) ASC
LIMIT 1;
如果你担心有一个" tie":
SELECT *
FROM table1
WHERE ABS(DATEDIFF(table1.Expiration, '2015-06-02')) = (
SELECT MIN(ABS(DATEDIFF(table1.Expiration, '2015-06-02')))
FROM table1
);
但请注意,这些查询永远不会很快;第二行要求对表中的每一行进行两次检查,并且在两种函数用法中都要求索引不提供任何帮助。
答案 1 :(得分:0)
如何简单地
SELECT *
FROM table1
ORDER BY ABS(DATEDIFF(Expiration, '2015-06-02'));
或者,如果表格很大,并且您有INDEX(Expiration)
,那么这应该更快:
( SELECT *,
ABS(DATEDIFF(Expiration, '2015-06-02')) AS diff
FROM table1
WHERE Expiration >= '2015-06-02'
ORDER BY Expiration ASC LIMIT 1 )
UNION ALL
( SELECT *,
ABS(DATEDIFF(Expiration, '2015-06-02')) AS diff
FROM table1
WHERE Expiration < '2015-06-02'
ORDER BY Expiration DESC LIMIT 1 )
ORDER BY diff
LIMIT 1;