【问题标题】:Convert correlated mysql subquery to noncorelated将相关的 mysql 子查询转换为非相关的
【发布时间】:2013-07-08 09:16:10
【问题描述】:

我需要帮助将相关子查询转换为不相关,这是一个查询:

http://sqlfiddle.com/#!2/2a67b/3

感谢您的建议

【问题讨论】:

  • 您希望退回什么?

标签: mysql subquery correlated-subquery


【解决方案1】:

我真的很难弄清楚你的 SQL 首先要做什么。

它似乎在最小和最大秒数之间获得每秒(嗯,比最大日期时间多 1 秒),并获得相应的记录计数。

如果是这样,那么最多应对 1000 秒:-

SELECT ADDDATE(MinCallDate, INTERVAL Sub1.i SECOND) AS aDate, COUNT(*)
FROM 
(
    SELECT MIN(calldate) AS MinCallDate, MAX(calldate) AS MaxCallDate
    FROM calls
)Sub0
CROSS JOIN
(
    SELECT units.i + tens.i * 10 + hundreds.i * 100 as i
    FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
) Sub1
INNER JOIN 
(
    SELECT calldate, ADDDATE(calldate, INTERVAL billsec SECOND) AS callenddate
    FROM calls
)   b
ON DATE_FORMAT(ADDDATE('2013-05-14 09:40:30', INTERVAL Sub1.i SECOND),"%Y%m%d%H%i%s") BETWEEN b.calldate AND b.callenddate
WHERE ADDDATE(MinCallDate, INTERVAL Sub1.i SECOND) <= MaxCallDate
AND Sub1.i < TIMESTAMPDIFF(SECOND,'2013-05-14 09:40:30', '2013-05-14 09:41:00')
GROUP BY aDate

如果您可以提供非 SQL 解释来说明您要达到的目标,我可能会想出更好的东西。

编辑 - 对于简单的计数:-

SELECT Sub1.TimeSecond, COUNT(Sub2.CallSecond)
FROM
(
    SELECT ADDDATE('2013-05-14 09:40:30', INTERVAL units.i + tens.i * 10 + hundreds.i * 100 + thousands.i * 1000 SECOND) AS TimeSecond
    FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) thousands
    HAVING TimeSecond BETWEEN '2013-05-14 09:40:30' AND '2013-05-14 09:41:00'
) Sub1
LEFT OUTER JOIN
(
    SELECT ADDDATE(calldate, INTERVAL units.i + tens.i * 10 + hundreds.i * 100 + thousands.i * 1000 SECOND) AS CallSecond
    FROM calls
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) thousands
    WHERE units.i + tens.i * 10 + hundreds.i * 100 + thousands.i * 1000 <= billsec
) Sub2
ON Sub1.TimeSecond = Sub2.CallSecond
GROUP BY Sub1.TimeSecond

这将处理长达 9999 秒的范围/电话呼叫(很容易将其扩展为更大的范围,但这会使其变慢。但是不确定这些是否会有效,因为 MySQL 不能真正使用索引对于任何联接。

这样会更简单,因为它不会在每次通话期间内每次都生成:-

SELECT Sub1.TimeSecond, COUNT(calls.calldate)
FROM
(
    SELECT ADDDATE('2013-05-14 09:40:30', INTERVAL units.i + tens.i * 10 + hundreds.i * 100 + thousands.i * 1000 SECOND) AS TimeSecond
    FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) thousands
    HAVING TimeSecond BETWEEN '2013-05-14 09:40:30' AND '2013-05-14 09:41:00'
) Sub1
LEFT OUTER JOIN calls
ON Sub1.TimeSecond BETWEEN calls.calldate AND ADDDATE(calls.calldate, INTERVAL calls.billsec SECOND)
GROUP BY Sub1.TimeSecond

你能改变表格的布局吗?如果是这样,为通话结束日期时间添加一列可能会有所帮助。

【讨论】:

  • 我需要计算给定时间间隔内的调用峰值数,实际上,如果我设置了一个间隔,例如 2013-05-14 09:00,那么两次之间的一行需要一秒:00 到 2013-05-14 10:00:00 需要有 3600 条记录。我不知道如何优化查询比现在快:)。谢谢
  • 所以表调用每个调用都有一行,其中包含该调用的开始时间和该调用的长度。您需要 2 个日期/时间之间的所有时间(以秒为单位)以及当时当前的通话次数吗?
  • 对了,计算当前通话的次数
  • 添加了一些其他建议
  • 表格的布局无法更改,因为它是电话服务器创建的默认布局,这是一个问题。但是感谢您的建议和帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
相关资源
最近更新 更多