我有一个看起来像的mysql查询:
(SELECT datum AS dt, dat1, dat2, num FROM maanden WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 2 YEAR, '%Y') AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y') ORDER BY datum ASC)
UNION
(SELECT datum AS dt, dat1, dat2, num FROM maanden WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y') AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW(), '%Y') ORDER BY datum ASC);
结果:
+---------------------+------+------+-----+
| dt | dat1 | dat2 | num |
+---------------------+------+------+-----+
| 2015-01-01 00:00:00 | 165 | 0 | 127 |
| 2015-02-01 00:00:00 | 101 | 0 | 81 |
| 2015-03-01 00:00:00 | 120 | 0 | 124 |
| 2015-04-01 00:00:00 | 106 | 0 | 49 |
| 2015-05-01 00:00:00 | 101 | 0 | 20 |
| 2015-06-01 00:00:00 | 117 | 0 | 19 |
| 2015-07-01 00:00:00 | 136 | 0 | 17 |
| 2015-08-01 00:00:00 | 184 | 0 | 8 |
| 2015-09-01 00:00:00 | 117 | 0 | 20 |
| 2015-10-01 00:00:00 | 173 | 0 | 59 |
| 2015-11-01 00:00:00 | 169 | 0 | 74 |
| 2015-12-01 00:00:00 | 257 | 0 | 108 |
| 2016-02-01 00:00:00 | 217 | 0 | 151 |
| 2016-03-01 00:00:00 | 123 | 0 | 72 |
| 2016-04-01 00:00:00 | 145 | 0 | 44 |
| 2016-05-01 00:00:00 | 169 | 0 | 30 |
| 2016-06-01 00:00:00 | 92 | 0 | 7 |
| 2016-07-01 00:00:00 | 143 | 0 | 9 |
| 2016-08-01 00:00:00 | 155 | 0 | 9 |
| 2016-09-01 00:00:00 | 150 | 0 | 11 |
| 2016-10-01 00:00:00 | 162 | 0 | 64 |
| 2016-11-01 00:00:00 | 170 | 0 | 113 |
| 2016-12-01 00:00:00 | 243 | 0 | 124 |
| 2016-01-01 00:00:00 | 190 | 0 | 123 |
+---------------------+------+------+-----+
24 rows in set (0.04 sec)
为什么2016-01-01 00:00:00
是最后一行?如果我只去年(没有UNION
):
(SELECT datum AS dt, dat1, dat2, num FROM maanden WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y') AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW(), '%Y') ORDER BY datum ASC);
我得到了正确的结果,是:
+---------------------+------+------+-----+
| dt | dat1 | dat2 | num |
+---------------------+------+------+-----+
| 2016-01-01 00:00:00 | 190 | 0 | 123 |
| 2016-02-01 00:00:00 | 217 | 0 | 151 |
| 2016-03-01 00:00:00 | 123 | 0 | 72 |
| 2016-04-01 00:00:00 | 145 | 0 | 44 |
| 2016-05-01 00:00:00 | 169 | 0 | 30 |
| 2016-06-01 00:00:00 | 92 | 0 | 7 |
| 2016-07-01 00:00:00 | 143 | 0 | 9 |
| 2016-08-01 00:00:00 | 155 | 0 | 9 |
| 2016-09-01 00:00:00 | 150 | 0 | 11 |
| 2016-10-01 00:00:00 | 162 | 0 | 64 |
| 2016-11-01 00:00:00 | 170 | 0 | 113 |
| 2016-12-01 00:00:00 | 243 | 0 | 124 |
+---------------------+------+------+-----+
12 rows in set (0.01 sec)
尝试使用()
并且没有()
的最后一个查询,但没有区别。任何帮助表示赞赏!
答案 0 :(得分:1)
每个查询的顺序都是开销。您需要按整个联合集进行排序。否则,每个订单仅适用于单个查询。
由于没有为整个联盟指定顺序,引擎可以按任何定义的顺序返回结果,它恰好是2016-12-01最后一次。
SELECT *
FROM (SELECT datum AS dt, dat1, dat2, num
FROM maanden
WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 2 YEAR, '%Y')
AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y')
UNION
SELECT datum AS dt, dat1, dat2, num
FROM maanden
WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y')
AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW(), '%Y')
)
ORDER BY datum ASC;
答案 1 :(得分:1)
您的查询按设计工作。行为在documentation of the UNION
SQL statement:
对单个
ORDER BY
语句使用SELECT
表示行在最终结果中的显示顺序,因为默认情况下UNION
会生成一组无序行。因此,在此上下文中使用ORDER BY
通常与LIMIT
结合使用,因此它用于确定要为SELECT
检索的所选行的子集,即使它不一定会影响最终UNION
结果中这些行的顺序。如果ORDER BY
中LIMIT
出现SELECT
,则会对其进行优化,因为它无论如何都无效。要使用
ORDER BY
或LIMIT
子句对整个UNION
结果进行排序或限制,请为各个SELECT
语句添加括号并放置ORDER BY
或{ {1}}在最后一个之后。
因此,执行您的预期的查询是:
LIMIT
作为旁注,您可以使用YEAR()
函数代替(
SELECT datum AS dt, dat1, dat2, num
FROM maanden
WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 2 YEAR, '%Y')
AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y')
)
UNION
(
SELECT datum AS dt, dat1, dat2, num
FROM maanden
WHERE DATE_FORMAT(datum, '%Y') >= DATE_FORMAT(NOW() - INTERVAL 1 YEAR, '%Y')
AND DATE_FORMAT(datum, '%Y') < DATE_FORMAT(NOW(), '%Y')
)
ORDER BY datum ASC
来简化查询(并提高其速度)。通过预先计算您想要比较的年份的第一天和最后一天(或日期时间),然后将DATE_FORMAT()
与它们进行比较,可以进一步提高其速度。