2012-08-04 77 views
1

我认为从我拥有的表格开始,我想要的结果是最简单的。count rows where date is equal but but name by

Name | Date 
A | 03/01/2012 
A | 03/01/2012 
B | 02/01/2012 
A | 02/01/2012 
B | 02/01/2012 
A | 02/01/2012 
B | 01/01/2012 
B | 01/01/2012 
A | 01/01/2012 

我想我的查询结果是:

Name | 01/01/2012 | 02/01/2012 | 03/01/2012 
A |  1  |  2  |  2 
B |  2  |  2  |  0 

所以基本上我想算具有相同日期的行数,但对于每一个人的名字。所以一个由日期组成的简单群组将不会执行,因为它会将这些名称合并在一起。然后我想输出一个表格,显示使用php的每个日期的计数。

我已经看到了答案建议是这样的:

SELECT 
    NAME, 
    SUM(CASE WHEN GRADE = 1 THEN 1 ELSE 0 END) AS GRADE1, 
    SUM(CASE WHEN GRADE = 2 THEN 1 ELSE 0 END) AS GRADE2, 
    SUM(CASE WHEN GRADE = 3 THEN 1 ELSE 0 END) AS GRADE3 
FROM Rodzaj 
GROUP BY NAME 

所以我想会有一个办法,我调整这一点,但我不知道是否有另一种方式,或者是最有效的? 我也许在想,如果while循环每次只输出一个特定的名字和日期,那么第一个结果就是A,01/01/2012,1,1下一个A,02/01/2012 ,2 - A,03/01/2012,3 - B,01/01/2012,2等等,那么也许这将是可行的通过一种不同的技术,但不知道如果这样的事情是可能的,如果它是有效的。

所以我基本上看看是否有人有任何想法,这是有点超出这个盒子,他们将如何比较。

我希望我解释得很好,并提前感谢您的帮助。

+0

SAME PROBLEM ---------------- >> http://stackoverflow.com/questions/14805851/mysql -sum-column-values-based-on-the-the-the-table – Smoke 2014-06-16 09:18:50

回答

2

您必须在您的GROUP BY两列:

SELECT name, COUNT(*) AS count 
FROM  your_table 
GROUP BY name, date 

这将让每一个名字的计数 - >行格式的日期组合。既然你也想包括0计数如果名字没有在特定日期的任何行,你可以使用:

SELECT  a.name, 
      b.date, 
      COUNT(c.name) AS date_count 
FROM  (SELECT DISTINCT name FROM your_table) a 
CROSS JOIN (SELECT DISTINCT date FROM your_table) b 
LEFT JOIN your_table c ON a.name = c.name AND 
          b.date = c.date 
GROUP BY a.name, 
      b.date 

SQLFiddle Demo

+0

那么这比我想象的要简单得多。按名称分组首先将所有日期合并在一起,所以我不会想到按列添加额外的分组将会产生任何影响。非常惊讶,但很好,谢谢。 – mrmryb 2012-08-04 19:35:26

+0

伟大的补充,我想知道现在是否会更有效地使用第一个查询选择日期以及做一个php检查匹配列或使用第二个查询。尽管由于sql很快,我想第二个查询仍然会更好。 – mrmryb 2012-08-04 19:45:11

2

你问一个“pivot ”。基本上,它就是这样。一个关键点的真正问题是名称名称必须适应数据,这对于单独的SQL是不可能的。

这里是你如何做到这一点:

SELECT 
    Name, 
    SUM(`Date` = '01/01/2012') AS `01/01/2012`, 
    SUM(`Date` = '02/01/2012') AS `02/01/2012`, 
    SUM(`Date` = '03/01/2012') AS `03/01/2012` 
FROM mytable 
GROUP BY Name 

注意凉爽的方式,你可以SUM() MySQL中的状态,becasue在MySQL true1false0,使总结的条件相当于数着数这是真的。

首先使用内部组没有更高的效率。

+0

查看哪个查询性能更好会很有趣,但是现在我向Zane提供了正确的答案,因为我要求的是不同的东西,他肯定会提供,但也非常感谢您提供非常有用的答案。 – mrmryb 2012-08-04 19:43:26

0

万一有人有兴趣在什么是最好的方法:

赞恩的第二个建议是最慢的,我装在我做了其他两个数据的三分之一,它花了相当长一段时间。也许在较小的表上它会更有效率,尽管我没有使用大型表,但大约28,000行足以产生显着的延迟,而between子句将结果减少到大约4000行。

波希米亚的答案给了我最少的代码量,我投入了一个循环来创建所有的case语句,并且它相对容易。这种方法的好处是简单,除了为案例创建循环外,结果不需要任何PHP技巧,只需简单的foreach即可获得所有列。推荐给那些对php没有信心的人。

但是,我发现Zane的第一个建议是最快的执行,尽管需要额外的PHP编码,似乎我会坚持使用这种方法。这种方法的缺点是它只给出实际上有数据的日期,因此创建一个包含所有日期的表格会变得更加复杂一些。我所做的是创建一个变量,用于跟踪它应该与每个表行重置的表列的日期进行比较,当查询结果等于该日期时,它会回显该值,否则它会执行一次操作while循环回显表格单元格为0,直到日期匹配。它还必须进行检查以查看'Name'值是否仍然相同,如果不是,则在填充任何缺失的单元格并将该行的末尾填入0之后切换到下一行。如果任何人有兴趣看到代码,你可以给我发消息。

两种方法超过3个月的数据(每一天,所以约90 case语句列)的结果〜12,000行了28000:
波西米亚的拐点 - 〜0.158s(最高见过〜0.36s)
赞恩的双分组由〜〜0.086s(最高可见〜0.15s)

相关问题