Php Mysql GROUP BY和COUNT用于多个WHERE子句
简化的表格结构:Php Mysql GROUP BY和COUNT用于多个WHERE子句,php,mysql,group-by,greatest-n-per-group,Php,Mysql,Group By,Greatest N Per Group,简化的表格结构: CREATE TABLE IF NOT EXISTS `hpa` ( `id` bigint(15) NOT NULL auto_increment, `core` varchar(50) NOT NULL, `hostname` varchar(50) NOT NULL, `status` varchar(255) NOT NULL, `entered_date` int(11) NOT NULL, `active_date` int(11) NOT
CREATE TABLE IF NOT EXISTS `hpa` (
`id` bigint(15) NOT NULL auto_increment,
`core` varchar(50) NOT NULL,
`hostname` varchar(50) NOT NULL,
`status` varchar(255) NOT NULL,
`entered_date` int(11) NOT NULL,
`active_date` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `hostname` (`hostname`),
KEY `status` (`status`),
KEY `entered_date` (`entered_date`),
KEY `core` (`core`),
KEY `active_date` (`active_date`)
)
对于这一点,我有下面的SQL查询,它简单地汇总所有具有已定义状态的记录
SELECT core,COUNT(hostname) AS hostname_count, MAX(active_date) AS last_active
FROM `hpa`
WHERE
status != 'OK' AND status != 'Repaired'
GROUP BY core
ORDER BY core
此查询已被简化,以删除不相关数据的内部联接和不应影响问题的额外列
MAX(active_date)对于特定日期的所有记录都是相同的,并且应该始终选择最近的一天,或者允许从现在开始偏移()。(这是一个UNIXTIME字段)
我想要两个计数:(状态!='OK'和状态!='Repaired')
而反过来。。。计数:(状态='OK'或状态='Repaired')
第一个答案除以第二个,表示“死亡百分比”(可能和后期处理一样快)
对于最近一天或抵消(-86400对于昨天等)
该表包含约500k条记录,每天增长约5000条,所以一个SQL查询而不是循环查询会非常好
我想一些有创意的IF可以做到这一点。感谢您的专业知识
编辑:我愿意对今天的数据或来自偏移量的数据使用不同的SQL查询
编辑:查询有效,速度足够快,但我目前无法让用户按百分比列(从坏计数和好计数派生的列)排序。这不是一个表演的阻碍,但我允许他们对其他一切进行排序。命令如下:
SELECT h1.core, MAX(h1.entered_date) AS last_active,
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS good_host_count,
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS bad_host_count
FROM `hpa` h1
LEFT OUTER JOIN `hpa` h2 ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date)
WHERE h2.hostname IS NULL
GROUP BY h1.core
ORDER BY ( bad_host_count / ( bad_host_count + good_host_count ) ) DESC,h1.core
如果我理解,您希望获得上次活动日期的OK与not OK主机名状态计数。对吗?然后应该按核心进行分组
SELECT core, MAX(active_date)
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2
ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date)
WHERE h2.hostname IS NULL
GROUP BY core
ORDER BY core;
选择堆芯,最大值(激活日期)
总和(状态为“正常”、“已修复”时的情况),然后为1,否则为0结束)作为正常主机计数,
合计(状态为“正常”、“已修复”时的情况),然后为0或1结束)作为断开的\u主机\u计数
从'hpa`h1向左外连接'hpa`h2
打开(h1.hostname=h2.hostname和h1.active\u日期
这是我在StackOverflow上的SQL问题中经常看到的“每个组最大n个”问题的变体
首先,我们希望只选择每个主机名具有最新活动日期的行,这可以通过对具有相同主机名和更大活动日期的行进行外部联接来实现。如果找不到这样的匹配项,则每个给定主机名都有最新的行
然后按核心分组并按状态计数行
这就是今天日期的解决方案(假设将来没有行具有活动的_日期)。要将结果限制为N天前的行,必须同时限制两个表
SELECT core, MAX(active_date)
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2
ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
AND h2.active_date <= CURDATE() - INTERVAL 1 DAY)
WHERE h1.active_date <= CURDATE() - INTERVAL 1 DAY AND h2.hostname IS NULL
GROUP BY core
ORDER BY core;
选择堆芯,最大值(激活日期)
总和(状态为“正常”、“已修复”时的情况),然后为1,否则为0结束)作为正常主机计数,
合计(状态为“正常”、“已修复”时的情况),然后为0或1结束)作为断开的\u主机\u计数
从'hpa`h1向左外连接'hpa`h2
打开(h1.hostname=h2.hostname和h1.active_日期 还有h2。活动日期谢谢你,比尔!不能马上测试这个,因为我今天已经完成了。我得到了第一部分。我想我必须研究一下第二部分。:)它实际上是一个整数存储历元时间,而不是日期时间。有区别吗?好的,它改变了计算偏移量的方式,但不改变一般逻辑。我再举个例子,谢谢。我无法打破将日期存储为历元的习惯,但我认为我有很好的理由,直到他们将微秒精度添加到datetime。使用epoch很容易。我不知道你说的是什么意思,因为UNIX\u TIMESTAMP()
以秒为单位测量时间,它是一个整数。那么微秒是从哪里来的呢?不管怎样,这与你原来的问题是正交的。
SELECT core, MAX(active_date)
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2
ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
AND h2.active_date <= CURDATE() - INTERVAL 1 DAY)
WHERE h1.active_date <= CURDATE() - INTERVAL 1 DAY AND h2.hostname IS NULL
GROUP BY core
ORDER BY core;
SELECT core, MAX(active_date)
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2
ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
AND h2.active_date <= UNIX_TIMESTAMP() - 86400)
WHERE h1.active_date <= UNIX_TIMESTAMP() - 86400 AND h2.hostname IS NULL
GROUP BY core
ORDER BY core;