SQL组合多个SELECT语句

时间:2017-09-07 17:59:15

标签: mysql sql sqlite datetime aggregate-functions

我正在尝试构建一个SQLite查询,它将从单个表中收集统计信息。

该表包含各种日志,每天有几个条目。我需要在搜索参数中为每一天获取一个单独的行,然后使用某些布尔值编译这些日期内的行总数。

这是我到目前为止的查询:

SELECT DATE(DateTime) AS SearchDate,
     (SELECT COUNT() AS Total
                FROM CallRecords
                WHERE DATE(DateTime)
                BETWEEN '2017-08-27' AND '2017-09-02'
                GROUP BY DATE(DateTime)
                ORDER BY Total DESC) AS Total,
    (SELECT COUNT() AS Total
                FROM CallRecords
                WHERE NoMarket = 1
                AND DATE(DateTime)
                BETWEEN '2017-08-27' AND '2017-09-02'
                GROUP BY DATE(DateTime)
                ORDER BY Total DESC) AS NoMarkets,
    (SELECT COUNT() AS Total
                FROM CallRecords
                WHERE Complaint = 1
                AND DATE(DateTime)
                BETWEEN '2017-08-27' AND '2017-09-02'
                GROUP BY DATE(DateTime)
                ORDER BY Total DESC) AS Complaints,
    (SELECT COUNT() AS Total
                FROM CallRecords
                WHERE Voicemail = 1
                AND DATE(DateTime)
                BETWEEN '2017-08-27' AND '2017-09-02'
                GROUP BY DATE(DateTime)
                ORDER BY Total DESC) AS Voicemails
FROM CallRecords
WHERE DATE(DateTime) BETWEEN '2017-08-27' AND '2017-09-02'
GROUP BY SearchDate

输出:

8/28/2017   175 27      11
8/29/2017   175 27      11
8/30/2017   175 27      11
8/31/2017   175 27      11
9/1/2017    175 27      11

正如您所看到的,它正确地获取每个日期,但列的总数不正确。

显然,我在查询中遗漏了一些内容,但我不知道在哪里。有没有更好的方法来执行此查询?

编辑:我已经在这里查看了几个其他几乎相同标题的问题,但我没有发现任何类似于我正在寻找的东西。大多数似乎比我想要完成的要复杂得多。

3 个答案:

答案 0 :(得分:5)

CallRecords表格中的列数看起来很乱,其中包含ComplaintVoicemail等名称,每个列都会对来电进行分类。

看起来这些列在相关时具有值1.

所以这个查询应该可以帮到你。

SELECT DATE(DateTime) AS SearchDate,
       COUNT(*) AS Total,
       SUM(NoMarket = 1) AS NoMarkets,
       SUM(Complaint = 1) AS Complaints,
       SUM(Voicemail = 1) AS Voicemails
  FROM CallRecords
 WHERE DateTime >=  '2017-08-27'
   AND DateTime <   '2017-09-02' + INTERVAL 1 DAY
 GROUP BY DATE(DateTime)

为什么这样做?因为在MySQL中,像Voicemail = 1这样的布尔表达式在其为真时具有值1,在它为假时具有0。你可以很好地总结这些值。

为什么它比你拥有的更快?因为DATE(DateTime) BETWEEN this AND that无法利用DateTime上的索引。

为什么日期范围结束时它是正确的?因为DateTime < '2017-09-02' + INTERVAL 1 DAY在日期范围之后的那天拉出所有记录,但不包括午夜。

如果您使用的是Sqlite,则需要AND DateTime < date('2017-09-02', '+1 day')。那里的+ INTERVAL 1 DAY内容略有不同。

答案 1 :(得分:1)

你可以这样做,虽然我在SQL server中写道

SELECT DATE(DateTime) AS SearchDate,
    COUNT() AS TOTAL,
    SUM(CASE WHEN NoMarket = 1 THEN 1 ELSE 0 END) AS NoMarkets,
    SUM(CASE WHEN Complaint = 1 THEN 1 ELSE 0 END) AS Complaints,
    SUM(CASE WHEN Voicemail = 1 THEN 1 ELSE 0 END) AS Voicemails
FROM CallRecords
WHERE DATE(DateTime) BETWEEN '2017-08-27' AND '2017-09-02'
GROUP BY SearchDate

答案 2 :(得分:0)

SELECT DATE(DateTime) AS SearchDate, Total, NoMarkets, Complaints, Voicemails FROM
 (SELECT COUNT() AS Total FROM CallRecords) CR
 JOIN
(SELECT COUNT() AS NoMarkets FROM CallRecords WHERE NoMarket = 1) NM
 ON CR.DateTime = NM.DateTime
 JOIN
(SELECT COUNT() AS Complaints FROM CallRecords WHERE Complaint = 1) C
 ON NM.DateTime = C.DateTime
 JOIN
(SELECT COUNT() AS Voicemails FROM CallRecords WHERE Voicemail = 1) VM
 ON C.DateTime = VM.DateTime
 JOIN CallRecords CLR ON VM.DateTime=CLR.DateTime WHERE DATE(CLR.DateTime) >= '2017-08-27' AND DATE(CLR.DateTime) <= '2017-09-02'GROUP BY SearchDate;

这可能输出正确。