将此PostgreSQL代码转换为MySQL的正确方法是什么?

时间:2018-03-23 16:13:33

标签: mysql postgresql

我正在尝试将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的正确方法是什么?

2 个答案:

答案 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