MySQL Couting按日期分组时的不同值

时间:2016-04-27 10:16:28

标签: mysql

我有两个表,一个是带有DATE列的日历表,另一个是包含每个ID的ID和三个DATES。

日历表:

 $stmt = $db->prepare("UPDATE employer 
     SET name='".$name."', phone='".$phone."',lname='".$lanme."' 
      WHERE username='".$_SESSION['username']."' ");

数据表:

dt
2016-01-01
2016-01-02
2016-01-03
2016-01-04
...

数据表确实包含许多其他字段,但我认为这与我的问题无关。我有一个查询,它从日历表中选择给定范围的DATE字段,比方说一个月,然后我使用所有三个DATE字段结合OR对数据表进行LEFT JOIN,因为我需要计算多个东西从数据表中,一些取决于d_created,一些取决于d_forwarded和其他d_solved:

ID          d_created          d_forwarded          d_solved
1           2016-01-01         2016-01-02           2016-01-03
2           2016-01-01         2016-01-02           2016-01-03
3           2016-01-02         2016-01-02           2016-01-04
4           2016-01-03         2016-01-04           2016-01-05
...

现在这是我的问题:当我没有通过tc.dt对结果进行分组时,查询会提供正确的输出,但是一旦我将其分组为tc.dt,结果就不正确。我绝不是SQL专家,但据我所知,由于JOIN,td.id将不止一次出现,只要我有一个结果行,DISTINCT就会阻止ID被计算两次

我需要能够计算在我的日期范围内创建,解决或转发的所有ID,并且我还需要日历表连接,因为我想在范围内显示每一天,即使可能存在如果有意义的话,我的数据表中没有特定日期的匹配日期。

有什么方法可以确保在按日分组时,不会多次计算任何ID?

我希望我能说清楚究竟是什么问题,如果没有,请告诉我,我会详细说明。

更新 我尝试使用SarathChandra示例,它看起来非常有前途,它确实提供了结果,但是只要我在CASE WHEN语句中添加更多条件,它就不会按预期方式工作。我分叉并修改了SarathChandra的想法小提琴HERE

所以它应该在2016-01-02日期返回1,但它显示0?

更新2 不幸的是,所提供的答案都没有能够解决潜在的问题。虽然这两个建议都得到了很多赞赏,但我最终将查询拆分为三个查询,每次都使用相同的日期范围加入日历表,然后将PHP中的数组合并到一个结果集中。

2 个答案:

答案 0 :(得分:0)

这里的问题是您加入了多个列,因此当您按日期分组时,您可以获得&#39> 2016-01-01&#的 ID 1 39; (已创建),' 2016-01-02' (已解决)和' 2016-01-03' (转发)。

您可以尝试连接同一个表3次,并将结果计入3列。然后,每列的总和应与记录数相匹配。

SQL Fiddle Example

查询:

SELECT tc.dt AS dt,
       COUNT(DISTINCT(CASE WHEN td_solved.id != 0
                      AND DATE(td_solved.d_solved) >= '2016-01-01'
                      AND DATE(td_solved.d_solved) <= '2016-01-31' THEN td_solved.id ELSE NULL END)) AS solved,
       COUNT(DISTINCT(CASE WHEN td_created.id != 0
                      AND DATE(td_created.d_created) >= '2016-01-01'
                      AND DATE(td_created.d_created) <= '2016-01-31' THEN td_created.id ELSE NULL END)) AS created,
       COUNT(DISTINCT(CASE WHEN td_forwarded.id != 0
                      AND DATE(td_forwarded.d_forwarded) >= '2016-01-01'
                      AND DATE(td_forwarded.d_forwarded) <= '2016-01-31' THEN td_forwarded.id ELSE NULL END)) AS forwarded
FROM calendar_table tc
LEFT JOIN data_table td_created ON tc.dt = DATE(td_created.d_created)
LEFT JOIN data_table td_solved ON tc.dt = DATE(td_solved.d_solved)
LEFT JOIN data_table td_forwarded ON tc.dt = DATE(td_forwarded.d_forwarded)
GROUP BY 1 WITH ROLLUP

答案 1 :(得分:0)

我在得出以下解决方案时对数据做了一些假设:

  1. d_created应位于d_forwarded之前,而d_solved则先于SELECT tc.dt AS dt, COUNT( CASE WHEN DATE(td.d_created) BETWEEN '2016-01-01' AND '2016-01-31' THEN td.id ELSE NULL END) AS `Count` FROM calendar_table tc LEFT JOIN data_table td ON (tc.dt = LEAST(DATE(td.d_created), DATE(td.d_solved), DATE(td.d_forwarded))) GROUP BY tc.dt;
  2. 为了删除重复的计数,即只计算一次记录一次,我将根据三个日期中最小的一个加入。
  3. 以下查询似乎对我有用。

    .TSS {
      border: 1px solid #000000;
      float: none;
      font-family: Verdana, Geneva, sans-serif;
      font-size: 10.6px;
      font-style: normal;
      padding: 10px;
      text-decoration: none;
      display: inline-block;
    }
    
    #centertbl {
      text-align: center;
    }
    
    .button {
      background-color: #4CAF50;
      /* Green */
      border: none;
      color: white;
      padding: 5px 15px;
      text-align: center;
      text-decoration: none;
      display: block;
      font-size: 16px;
      margin: 4px 2px;
      -webkit-transition-duration: 0.4s;
      /* Safari */
      transition-duration: 0.4s;
      cursor: pointer;
    }
    
    .button1 {
      background-color: white;
      color: black;
      border: 2px solid #4CAF50;
    }
    
    .button1:hover {
      background-color: #4CAF50;
      color: white;
    }
    
    .images-area {
      position: relative;
      margin: 0 0 15px;
    }
    
    .red-square {
      display: block;
      margin: 0 auto;
    }
    
    .black-circles {
      position: absolute;
      margin-top: -60px;
      left: 10px;
      top: 50%;
    }
    
    .black-circles img {
      margin: 0 0 -15px;
      max-width: 100%;
      display: block;
      height: auto;
    }

    更新:工作示例代码here