我正在尝试将PostgreSQL代码转换为MySQL,我有点卡住了。我遇到问题的部分看起来像
SELECT (SELECT COUNT(1) FROM table1 WHERE id = o.id AND state = 'processing') AS number
FROM table2 o
WHERE TO_TIMESTAMP(time) >= '2018-03-19' AND TO_TIMESTAMP(time) <= '2018-03-20'
这在PostgreSQL中运行得非常好。将它转换为MySQL我试过
SELECT (SELECT COUNT(1) FROM table1 WHERE id = o.id AND state = 'processing') AS number
FROM table2 o
WHERE FROM_UNIXTIME(time) >= '2018-03-19' AND FROM_UNIXTIME(time) <= '2018-03-20'
但不幸的是,代码永远运行并提供了无效的结果。
我也试过
SELECT (SELECT COUNT(1) FROM table1 l JOIN table2 o ON l.id = o.id WHERE state = 'processing' AND FROM_UNIXTIME(time) >= '2018-03-19' AND FROM_UNIXTIME(time) <= '2018-03-20') AS number
FROM table2 o
WHERE FROM_UNIXTIME(time) >= '2018-03-19' AND FROM_UNIXTIME(time) <= '2018-03-20'
仍然没有给出准确的结果。将它转换为MySQL的正确方法是什么?
答案 0 :(得分:3)
我建议在谓词中引用裸列,并在文字方面进行转换。
如果列time
被定义为整数类型,并且是1970-01-01 00:00:00以来的unix样式整数秒数,我们可以将文字'2018-03-19'转换为右侧为整数秒。
这将使MySQL能够对以time
为前导列的索引执行范围扫描操作。
我还建议对所有列引用进行限定,以避免歧义,并为未来的读者提供帮助。
SELECT ( SELECT COUNT(1)
FROM table1 n
WHERE n.id = o.id
AND n.state = 'processing'
) AS number
FROM table2 o
WHERE o.time >= UNIX_TIMESTAMP('2018-03-19')
AND o.time < UNIX_TIMESTAMP('2018-03-20')
就性能而言,SELECT列表中的相关子查询将吃掉我们的午餐,因为它将针对外部查询返回的每一行执行。
我们使用EXPLAIN
来查看执行计划。对于大型集合,我们希望提供合适的索引。例如,涵盖索引:
... ON `table2` (`time`,`id`)
... ON `table1` (`id`,`state`)
我们希望在Extra列中看到有效的“范围”操作和“使用索引”,表示从索引中满足查询,而不查找数据页。
此外,我们假设表格使用InnoDB,缓冲池的大小适当。
另请注意,我做了一个“小于”的比较而不是高于“小于或等于”的比较。这是我使用的典型模式......如果我还要运行查询以获取3月20日的数字,我不希望在3月19日和3月20日的计数中包含相同的行。
如果table2
有PRIMARY KEY(或UNIQUE KEY)或某些列(或列集),我会试图避开相关子查询并使用条件聚合执行JOIN操作。
SELECT IFNULL(SUM(n.state='processing'),0) AS `number`
FROM table2 o
LEFT
JOIN table1 n
ON n.id = o.id
WHERE o.time >= UNIX_TIMESTAMP('2018-03-19')
AND o.time < UNIX_TIMESTAMP('2018-03-20')
GROUP BY o.unique_key
答案 1 :(得分:0)
SELECT num
FROM (SELECT tablea.id,
CASE WHEN (count(tablec.id))IS NULL THEN 0 ELSE (count(tablec.id)) END as num
FROM (SELECT id,
FROM table2 o
WHERE DATE(FROM_UNIXTIME(time))>= '2018-03-19'
AND DATE(FROM_UNIXTIME(time))<= '2018-03-20'
) as tablea
LEFT JOIN (SELECT distinct(id),
action
FROM table1
WHERE state = 'processing'
) as tableb ON tablea.id = tableb.id
LEFT JOIN (SELECT id,
action
FROM table1
WHERE state = 'processing'
) as tablec ON tablea.id = tablec.id
GROUP BY tablea.id
) as tt