MYSQL多次计数在带有连接的表上

时间:2015-12-11 01:17:38

标签: mysql count

好的,我有这个SQL查询

$query = "
            SELECT
                c.category, count(t.id_ticket) as ticket_count, count(tm.id_message) as message_count
            FROM
                tickets t
            LEFT JOIN
                ticketMessages tm
            ON
                t.id_ticket = tm.id_ticket
            LEFT JOIN
                categories c
            ON
                t.id_category = c.id_category
            GROUP BY
                t.id_category
        ";

所以基本上我有一张票证表,每张票可以有多条消息,每张票都有一个分配给它的类别。

现在让我们假设以下

我在红色类别中有2张票,总共有5条消息 我在蓝色类别中有4张票,总共有10条消息 我在黑色类别中有3张票,共有7条消息

我想做的是展示这样的东西:

[0]=>
  array(4) {
    ["category"]=>
    string(12) "Red"
    ["id_ticket_count"]=>
    string(1) "2"
    ["id_message_count"]=>
    string(1) "5"
  }
[1]=>
array(4) {
  ["category"]=>
  string(12) "Blue"
  ["id_ticket_count"]=>
  string(1) "4"
  ["id_message_count"]=>
  string(2) "10"
}
[1]=>
array(4) {
  ["category"]=>
  string(12) "Black"
  ["id_ticket_count"]=>
  string(1) "3"
  ["id_message_count"]=>
  string(2) "7"
}

但是我的SQL为消息和票证返回相同的值,该值是消息,但我也想知道票数。我假设计算id_ticket。

如果我通过t.ticket_id添加组,那么它会显示每个票证的新数组项,所以我最终得到2个红色类别项目,4个蓝色和3个黑色项目,但它应该只显示每个类别1个项目的计数对于每个类别。

如果它有助于表格看起来像这样

Category
id_category | category
1 | red
2 | blue
3 | black

Tickets
id_ticket | id_category 
1 | 1
2 | 1
3 | 2
4 | 2
5 | 2
6 | 2
7 | 3
8 | 3
9 | 3

Messages
id_message | id_ticket
1 | 1
2 | 1
3 | 2
4 | 2
5 | 2
6 | 3
7 | 3
8 | 3
9 | 4
10 | 4
11 | 4
12 | 5
13 | 5
14 | 5
15 | 6
16 | 7
17 | 7
18 | 8
19 | 8
20 | 9
21 | 9
22 | 9

5 个答案:

答案 0 :(得分:1)

您可能会尝试使用CASE WHEN子句更准确地处理基数问题。据我所知,使用 count 会导致 NULL 值,因为那些没有分配消息的票证会被计为1个误导性的有效行。

也许像

           SELECT
            c.category, count(t.id_ticket) as ticket_count,
            SUM(CASE WHEN tm.id_message IS NOT NULL THEN 1 ELSE 0 END) as message_count
        FROM
            tickets t
        LEFT JOIN
            ticketMessages tm
        ON
            t.id_ticket = tm.id_ticket
        LEFT JOIN
            categories c
        ON
            t.id_category = c.id_category
        GROUP BY
            t.id_category

我假设故障单 ticketMessages 之间存在 1:很多关系。

答案 1 :(得分:0)

这应该能满足您的需求。您需要获得DISTINCT票证,同时获得消息的总计数

SELECT
      c.category,
      COUNT( distinct t.id_ticket ) as UniqueTickets,
      COUNT(tm.id_ticket) TotalMsgsPerTickets
   from
      Categories c
         LEFT JOIN tickets t
            ON c.id_category = t.id_Category
            left join ticketMessages tm
               ON t.id_ticket = tm.id_ticket
   group by
      c.id_Category

答案 2 :(得分:0)

您可以将子查询用于最低级别的表来实现此目的:

SELECT  c.category, 
    count(t.id_ticket) as ticket_count,
    SUM((SELECT COUNT(*) FROM ticketMessages WHERE id_ticket =  t.id_ticket)) as message_count
    FROM tickets t
    INNER JOIN categories c ON t.id_category = c.id_category
    GROUP BY t.id_category

答案 3 :(得分:0)

  

所以基本上我有一张票证表,每张票可以有多条消息

我假设每张票都有消息,根本没有消息。

  

并且每个故障单都有一个分配给它的类别。

并且所有门票都应该有自己的相应类别。

根据您想要的结果,您可以使用此查询:

SELECT C.category
  , COUNT(DISTINCT T.id_ticket) AS id_ticket_count
  , COUNT(M.id_ticket) AS id_message_count
  FROM Category C
  INNER JOIN Tickets T ON T.id_category = C.id_category
  LEFT JOIN Messages M ON M.id_ticket = T.id_ticket
  GROUP BY C.id_category

请在SQL Fiddle Demo中查看结果。

答案 4 :(得分:0)

Count将返回group by中指定的每个组的总返回行数。

Count(Distinct "fieldName")将返回指定字段的非重复值计数。 在您的情况下:count(t.id_ticket)count(tm.id_message)或甚至count(*)将返回相同的值(每个组的行数)。

从给出SQL语句,您还应该注意GROUP BY子句,因为MySql允许您使用奇怪的组合!通常要记住,Select子句中的任何列都没有聚合,应该包含在group by子句中。