我有一个MySQL表,每个人都有很多行,我想写一个聚合具有特殊约束的行的查询。 (每人一个)
例如,假设该表包含以下数据。
name date reason
---------------------------------------
John 2013-04-01 14:00:00 Vacation
John 2013-03-31 18:00:00 Sick
Ted 2012-05-06 20:00:00 Sick
Ted 2012-02-20 01:00:00 Vacation
John 2011-12-21 00:00:00 Sick
Bob 2011-04-02 20:00:00 Sick
我想看看'reason'栏的分布情况。如果我只是写下面的查询
select reason, count(*) as count from table group by reason
然后我将能够看到整个表格的原因。
reason count
------------------
Sick 4
Vacation 2
但是,我只对每个人的单一理由感兴趣。应该计算的原因应该是来自该人员记录的最新日期。例如,John的最新理由是Vacation
,而Ted的最新理由是Sick
。鲍勃的最新理由(也是唯一的原因)是Sick
。
该查询的预期结果应如下所示。 (计数总和将为3,因为只有3人)
reason count
-----------------
Sick 2
Vacation 1
当我想查看原因的分布(计数)时,是否可以编写一个查询,以便计算单个最新原因?
以下是关于该表的一些事实。
答案 0 :(得分:1)
SELECT T.REASON, COUNT(*)
FROM
(
SELECT PERSON, MAX(DATE) AS MAX_DATE
FROM TABLE-NAME
GROUP BY PERSON
) A, TABLE-NAME T
WHERE T.PERSON = A.PERSON AND T.DATE = A.MAX_DATE
GROUP BY T.REASON
答案 1 :(得分:0)
试试这个
select reason, count(*) from
(select reason from table where date in
(select max(date) from table group by name)) t
group by reason
答案 2 :(得分:0)
您正在寻找的解决方案似乎可以通过此查询解决:
select
reason,
count(*)
from (select * from tablename group by name) abc
group by
reason
它非常快速而简单。您可以查看SQL Fiddle
答案 3 :(得分:0)
在MySQL中,由于您无法访问partitionning query in SQL Server或Oracle等工具,因此执行此类查询效率不高。
您仍然可以通过执行子查询来模拟它,并根据您需要的条件检索行,这里是最大日期:
SELECT t.reason, COUNT(1)
FROM
(
SELECT name, MAX(adate) AS maxDate
FROM @aTable
GROUP BY name
) maxDateRows
INNER JOIN @aTable t ON maxDateRows.name = t.name
AND maxDateRows.maxDate = t.adate
GROUP BY t.reason
You can see a sample here.
在你的样品上测试这个查询,但我担心它会慢下来。
为了您的信息,您可以在SQL Server中以更优雅,更快的方式执行相同的操作:
SELECT reason, COUNT(1)
FROM
(
SELECT name
, reason
, RANK() OVER(PARTITION BY name ORDER BY adate DESC) as Rank
FROM @aTable
) AS rankTable
WHERE Rank = 1
GROUP BY reason
如果您真的遇到MySql,并且第一个查询太慢,那么您可以解决问题。
创建表格的第一个查询:
CREATE TABLE maxDateRows AS
SELECT name, MAX(adate) AS maxDate
FROM @aTable
GROUP BY name
然后在name和maxDate上创建索引 最后,得到结果:
SELECT t.reason, COUNT(1)
FROM maxDateRows m
INNER JOIN @aTable t ON m.name = t.name
AND m.maxDate = t.adate
GROUP BY t.reason
答案 4 :(得分:0)
如果此答案与现有答案重复,请道歉。也许我患有某种形式的失语症,但我看不到它......
SELECT x.reason
, COUNT(*)
FROM absentism x
JOIN
( SELECT name,MAX(date) max_date FROM absentism GROUP BY name) y
ON y.name = x.name
AND y.max_date = x.date
GROUP
BY reason;