在 MySQL 中应用查询之前过滤表

Posted

技术标签:

【中文标题】在 MySQL 中应用查询之前过滤表【英文标题】:Filter table before applying query in MySQL 【发布时间】:2017-10-14 08:24:16 【问题描述】:

我有一个名为push_message_infomysql 表,我想对其进行过滤然后计算一些结果。得到结果的查询是:

SELECT p.pending, s.success, t.total
FROM 
    (SELECT count(*) AS pending FROM push_message_info WHERE served < total) AS p,
    (SELECT count(*) AS success FROM push_message_info WHERE served = total) AS s,
    (SELECT count(*) AS total FROM push_message_info) AS t
;

问题是我只想计算最新的条目。因为它有一个名为 submit_date 的日期时间字段,所以我认为这样的事情会起作用:

SELECT p.pending, s.success, t.total
FROM 
    (SELECT * FROM push_message_info WHERE DATE(submit_date) > '2017-05-14') AS filtered
    (SELECT count(*) AS pending FROM filtered WHERE served < total) AS p,
    (SELECT count(*) AS success FROM filtered WHERE served = total) AS s,
    (SELECT count(*) AS total FROM filtered) AS t
;

但它给我带来了错误:

错误 1146 (42S02):表 'unifiedpush.filtered' 不存在

如何过滤/限制原始表,以便在该新表上应用其他查询?

【问题讨论】:

必须是unifiedpush.push_message_info,不能是push_message_info吗? 见:Why should I provide an MCVE for what seems to me to be a very simple SQL query? @XtremeBaumer 真的没关系,为了简单起见我删除了它,但在第二个查询中忘记了它,我现在将其删除。 @Strawberry 我看不出我可以添加什么示例,因为问题是关于查询本身而不是数据。 何塞,你似乎决心阻止其他人提供帮助。它正在工作。 【参考方案1】:

您的查询总体上不太好。 您可以通过一个简单的查询来完成所有这些子查询,而不是创建所有这些子查询。

SELECT 
    SUM(CASE WHEN served < total THEN 1 ELSE 0 END) AS pending,
    SUM(CASE WHEN served = total THEN 1 ELSE 0 END) AS served,
    COUNT(*) as total
FROM push_message_info
WHERE DATE(submit_date) > '2017-05-14';

我已将counts(total 除外)换成SUM(CASE WHEN ... THEN 1 ELSE 0 END),让您可以进行条件计数。

【讨论】:

抱歉,您并没有真正回答所问的问题。 它为您提供所需的数据。告诉我它为什么没有回答你的问题,这样我就可以改进我的回答。 所以我想要实现的是过滤表并将这个视图重命名为“已过滤”。一旦我得到这个“中间”表,就对其应用查询。这与输出或日期无关,更多的是要了解子查询的工作原理。【参考方案2】:

您查询中的问题是过滤别名的范围:它在其他子查询中不可见。

如果你真的想拥有它,你可以创建一个视图:

create view filtered as SELECT * FROM push_message_info WHERE DATE(submit_date) > '2017-05-14';

SELECT p.pending, s.success, t.total
FROM
    (SELECT count(*) AS pending FROM filtered WHERE served < total) AS p,
    (SELECT count(*) AS success FROM filtered WHERE served = total) AS s,
    (SELECT count(*) AS total FROM filtered) AS t;

【讨论】:

谢谢老兄,虽然我知道这可能不是最有效的方法,但现在我明白为什么我的查询不起作用了。【参考方案3】:

好吧,我可以告诉你我是如何完成这样的事情的。试试:

SELECT SUM(IF(served < total, 1, 0)) as pending,
       SUM(IF(served = total,1 ,0)) AS success,
       COUNT(*) as total
  FROM push_message_info
 WHERE DATE(submit_date) > '2017-05-14';

这应该可以满足您的需求...

【讨论】:

这不是我真正想知道的。顺便说一句,它失败了。 不知道为什么会失败。我没有你的数据,所以我用眼睛构造了它,但我只是做了一个类似的查询,if() 函数工作正常。您能否详细说明您希望输出的外观?当我阅读您的 SQL 和您的问题时,您想要计算 [结束、成功和新提交的总数...我错过了什么吗? 我刚刚看到了错误。删除总计后的逗号,它应该可以工作。那是一个错字。对不起 所以重点并不是真正的输出。我想要实现的是“创建”一个“中间”表,以便我可以对其运行一些查询。这个“中间”表将是过滤日期的结果。 也许这会有所帮助?它谈到了从选择中创建一个临时表:http://***.com/questions/5859391/create-a-temporary-table-in-a-select-statement-without-a-separate-create-table。

以上是关于在 MySQL 中应用查询之前过滤表的主要内容,如果未能解决你的问题,请参考以下文章

如何使用另一个查询结果过滤MySQL表

MySQL单表查询(分组-筛选-过滤-去重-排序)

请教大家!mysql查询结果,过滤重复数据?

SQLAlchemy:如何在连接查询中的过滤器之前应用 distinct

python开发mysql:单表查询&多表查询

MySQL-查询