【问题标题】:combine multiple count/group queries into one statement将多个计数/组查询合并到一个语句中
【发布时间】:2014-06-22 10:54:30
【问题描述】:

我一直在尝试一种方法来为多个表中的用户返回计数。

<?php

    $stmt = $db->prepare("SELECT `computer_username`, `computer_name`, COUNT(`computer_name`) `totalsum` FROM `table1`
        WHERE `account_id` = ? AND (`computer_name` = 'comp1' OR `computer_name` = 'comp2' OR `computer_name` = 'comp3')
        GROUP BY `computer_username`, `computer_name`
    ");

    $stmt->execute(array($_SESSION['user']['account_id']));
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);   
    //print out the array
    echo 'table1<br /><pre>',print_r($results,true),'</pre><br /><br />';

    $stmt = $db->prepare("SELECT `computer_username`, `computer_name`, COUNT(`computer_name`) `totalsum` FROM `table2`
        WHERE `account_id` = ? AND (`computer_name` = 'comp1' OR `computer_name` = 'comp2' OR `computer_name` = 'comp3')
        GROUP BY `computer_username`, `computer_name`
    ");

    $stmt->execute(array($_SESSION['user']['account_id']));
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);   
    //print out the array
    echo 'table2<br /><pre>',print_r($results,true),'</pre><br /><br />';

    $stmt = $db->prepare("SELECT `computer_username`, `computer_name`, COUNT(`computer_name`) `totalsum` FROM `table3`
        WHERE `account_id` = ? AND (`computer_name` = 'comp1' OR `computer_name` = 'comp2' OR `computer_name` = 'comp3')
        GROUP BY `computer_username`, `computer_name`
    ");

    $stmt->execute(array($_SESSION['user']['account_id']));
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);   
    //print out the array
    echo 'table3<br /><pre>',print_r($results,true),'</pre><br /><br />';

?>

这导致每个数组的结果类似于以下内容:

Array
(
    [0] => Array
        (
            [computer_username] => Bob
            [computer_name] => comp1
            [totalsum] => 1
        )

    [1] => Array
        (
            [computer_username] => Steve
            [computer_name] => comp1
            [totalsum] => 27
        )

    [2] => Array
        (
            [computer_username] => Sue
            [computer_name] => comp2
            [totalsum] => 7
        )

)

我只是想为每个表返回数据库中每个组的总行数。由于条件完全相同,只有表名不同,有没有办法一次调用全部返回?我整天都在玩它,但到目前为止,对每个都使用查询是我获得结果的唯一方法。

理想情况下,我正在寻找一个类似的数组结果:

Array
(
    [0] => Array
        (
            [computer_username] => Bob
            [computer_name] => comp1
            [table1] => 15
            [table2] => 34
            [table3] => 131
        )

        ... and so on for each computer_name/computer_username group

)

编辑:

我在这方面取得了一些进展......

SELECT * FROM

(SELECT computer_name, username, COUNT(computer_name) usercount
FROM users
WHERE `account_id` = ?
GROUP BY `username`, `computer_name`) a

JOIN 

(SELECT computer_name, computer_username, COUNT(computer_name) t1count
FROM t1
WHERE `account_id` = ?
GROUP BY `computer_username`, `computer_name`) b

JOIN

(SELECT computer_name, computer_username, COUNT(computer_name) t2count
FROM t2
WHERE `account_id` = ?
GROUP BY `computer_username`, `computer_name`) c

JOIN

(SELECT computer_name, computer_username, COUNT(computer_name) t3count
FROM t3
WHERE `account_id` = ?
GROUP BY `computer_username`, `computer_name`) d

ON a.username = b.computer_username AND a.username = c.computer_username AND a.username = d.computer_username

我从users 表开始,因为它总是列出所有用户名/计算机组组合。问题是要在数组中返回任何结果,用户名/计算机组也必须在每个其他表中都有条目(t1,t2,t3)。

也就是说,计算机 1 上的 Bob 在 t1 中有 5 行,在 t2 中有 10 行,在 t3 中有 50 行,我会将这些计数作为 t1count、t2count、t3count 返回到我的数组中。计算机 4 上的 Sue 在 t1、0 和 t2 中有 5 个,在 t3 中有 12 个...因为 t2 中没有行,所以没有返回任何结果。

有没有办法解决这个问题,或者连接是否明确要求从一个表到下一个表的匹配值?

示例数据和预期结果:

//always contains every unique username/computer_name combination
`users` (username, computer_name)

bob, computer1
bob, computer8
steve, computer1
joe, computer3
sal, computer4
cindy, computer4
bill, computer8
jack, computer2

//contains data by computer_username/computer_name combo (can repeat)
`table1` (computer_username, computer_name)

bob, computer1
bob, computer8
bob, computer8
bob, computer8
steve, computer1
joe, computer3
joe, computer3
joe, computer3
bill, computer8
sal, computer4
sal, computer4
sal, computer4
cindy, computer4
bill, computer8

//contains data by computer_username/computer_name combo (can repeat)
`table2` (computer_username, computer_name)

bob, computer1
bob, computer1
bob, computer1
bob, computer8
bob, computer8
joe, computer3
joe, computer3
bill, computer8
sal, computer4
sal, computer4
cindy, computer4
cindy, computer4
cindy, computer4

//contains data by computer_username/computer_name combo (can repeat)
`table3` (computer_username, computer_name)

bob, computer8
steve, computer1
steve, computer1
steve, computer1
bill, computer8
bill, computer8
steve, computer1
sal, computer4
cindy, computer4
cindy, computer4

// resulting array on account_id = 1 and computer_name = (computer1, computer2, computer3, or computer4)
Array
(
    [0] => Array
        (
            [computer_username] => bob
            [computer_name] => computer1
            [t1count] => 1
            [t2count] => 3
            [t3count] => 0
        )
    [1] => Array
        (
            [computer_username] => steve
            [computer_name] => computer1
            [t1count] => 1
            [t2count] => 0
            [t3count] => 3
        )
    [3] => Array
        (
            [computer_username] => joe
            [computer_name] => computer3
            [t1count] => 3
            [t2count] => 2
            [t3count] => 0
        )
    [4] => Array
        (
            [computer_username] => sal
            [computer_name] => computer4
            [t1count] => 3
            [t2count] => 2
            [t3count] => 1
        )
    [5] => Array
        (
            [computer_username] => cindy
            [computer_name] => computer4
            [t1count] => 1
            [t2count] => 3
            [t3count] => 2
        )
    [6] => Array
        (
            [computer_username] => jack
            [computer_name] => computer2
            [t1count] => 0
            [t2count] => 0
            [t3count] => 0
        )
)

假设,以上所有表格都有一个名为 account_id = 1 的列。您有一个代表计算机“所有者”的 account_id。用户是所有计算机和这些计算机上所有用户名的表。 table1、table2、table3 是与特定计算机和该计算机的特定用户相关的记录。任何这些表中的任何特定用户/计算机对都可以有零个或任意数量的记录。

目标是为给定 account_id 和计算机名列表的每个用户返回记录表(table1、table2、table3)的计数。结果不需要任何排序。

【问题讨论】:

  • 你不能加入表格吗?一键选择
  • 见联合。另外,考虑一下:“AND computer_name IN ('comp1','comp2','comp3')”。如需进一步帮助,请考虑提供适当的 DDL(和/或 sqlfiddle)以及所需的结果集。

标签: php mysql sql pdo


【解决方案1】:

使用提供的数据并且没有提供用于查询的 ID 将满足您的需求。 见工作FIDDLE

SELECT 
  usr, 
  cmptr, 
  t1_count, 
  t2_count, 
  t3_count 
FROM (
  SELECT
    users.username AS usr,
    users.computer_name AS cmptr,
    count(t1.computer_name) AS t1_count
  FROM users
  JOIN t1 ON t1.computer_username = users.username AND t1.computer_name = users.computer_name
  GROUP BY users.username, users.computer_name
)AS t
LEFT JOIN(
  SELECT
    users.username,
    users.computer_name,
    count(t2.computer_name) AS t2_count
  FROM users
  JOIN t2 ON t2.computer_username = users.username AND t2.computer_name = users.computer_name
  GROUP BY users.username, users.computer_name
) AS te ON te.username = t.usr OR te.computer_name = t.cmptr
LEFT JOIN(
  SELECT
    users.username,
    users.computer_name,
    count(t3.computer_name) AS t3_count
  FROM users
  JOIN t3 ON t3.computer_username = users.username AND t3.computer_name = users.computer_name
  GROUP BY users.username, users.computer_name
) AS tem ON tem.username = t.usr OR tem.computer_name = t.cmptr
GROUP BY usr, cmptr

【讨论】:

  • 我试过了,但它抛出了一个''SQLSTATE[42000]:语法错误或访问冲突:1064'......我试图尽可能地解释它。想象一下我发布的数组结果是第一个表的结果。将有两个类似的具有相同的计算机用户名/计算机名组合。尝试在一个结果数组中获取每个表的组计数。
  • @user756659 为什么你忽略了错误消息中唯一有意义的部分?
  • 如果您可以提供有关错误消息的更多详细信息,例如语法是什么,我们可以提供更多帮助。如果你能提供一些原始数据(比如每个表中的几行),我可以构建一个 sql fiddle 并让它工作。
  • 我添加了一些数据......希望这是有道理的。我可以在一个循环中对此进行单独的查询,但现在我只想看看它是否可能比什么都重要。另外,这有助于我在学习过程中了解更多......我显然需要通过这样的查询来增加我的知识。
  • 好吧,我马上看看。应该是可能的。但是通常我认为最好为每个用户提供 id 并在其他表中将外键作为 user_id 以使其更加规范化。
猜你喜欢
  • 2018-11-22
  • 1970-01-01
  • 2022-01-20
  • 2015-02-02
  • 2019-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多