【问题标题】:How to display all rows from one table if there are no rows with matching criteria to count in second table如果没有符合条件的行在第二个表中计数,如何显示一个表中的所有行
【发布时间】:2019-05-21 22:42:56
【问题描述】:

我有两张桌子。 “members”是所有成员的列表,“stats”是工作日期的列表。共享字段是 memberID。我需要每个人工作天数的 COUNT 个,并且我希望每个人都列在输出表中,即使他们还没有工作日。

简化的数据库结构是:

**members**                 **stats**       
memberID lname    fname     memberID    date    statsID
1        Mertz    Fred      1        2017-12-31    1
2        Doe      Jane      3        2017-12-31    2
3        Smith    Frank     4        2017-12-31    3
4        Ricardo  Lucy      2        2018-12-31    4
5        Starr    Ringo     4        2018-12-31    5
                            2        2019-05-05    6
                            3        2019-05-05    7

所需的输出是:

memberID  lname  fname  Total Days 
2         Doe    Jane       2 
1         Mertz  Fred       1 
4         Ricardo Lucy      2 
3         Smith   Frank     2 
5         Starr   Ringo     0 OR blank

Ringo 任何天都没有工作,也没有出现在输出表上。

我的代码是:

$sql = "SELECT  u.*,
   COUNT(s.memberID)as tot_days
   FROM members u
   LEFT JOIN stats s
    ON s.memberID = u.memberID 
    GROUP BY s.memberID
    ORDER BY lname,fname";

$members = mysqli_query($dbc,$sql) or die(mysqli_error());

while ($row = mysqli_fetch_array($members)){ 
        $row = array_map('htmlspecialchars', $row);
        echo <<< HTML  etc.

除了包括那些还没有工作一天的成员之外,我希望它可以做所有事情。 JOIN、LEFT JOIN、LEFT OUTER JOIN、RIGHT JOIN、RIGHT OUTER JOIN 都产生相同的结果。我尝试了 LEFT 和 RIGHT INNER JOIN,如果它们甚至存在,则会产生错误Warning: mysqli_error() expects exactly 1 parameter, 0 given

有人建议使用COALESCE (COUNT(s.memberID),0) as tot_days,但这只会产生与上述相同的错误。

我已经为此工作了好几天,现在有点沮丧!

【问题讨论】:

  • 所以给mysqli_error()它想要的参数mysqli_error($dbc),看看错误是什么。可能与聚合使用不正确有关(SELECT 之后列出的列既不是聚合函数的参数,也不是在 GROUP BY 中列出)。
  • Miken32 的解决方案确实有效。它选择了几个没有工作日期的新成员之一。我的样本应该包含不止一个。我试图在他的帖子中添加评论,但它不允许我。
  • 按 u.memberid 分组
  • 这是您的原始查询还是已被编辑?因为它确实根据您的预期输出返回。

标签: php mysql join count


【解决方案1】:
SELECT u.*
     , COUNT(DISTINCT s.date) tot_days
  FROM members u
  LEFT 
  JOIN stats s
    ON s.memberID = u.memberID
 GROUP 
    BY u.memberID
 ORDER 
    BY u.lname
     , u.fname

【讨论】:

  • 除了简单地回答问题,您还应该解释为什么您的答案比 OP 问题中的代码更好/不同。
  • @BevHorn 将 WHERE 更改为 AND
  • 谢谢草莓,我真笨!您的新建议效果很好。现在,幸运的是,我可以将它们合二为一。但至少我现在有了一些有用的东西。
【解决方案2】:

你将不得不重新构建你的查询

create table members (id int primary key auto_increment, lname varchar(30), fname varchar(30));
insert into members values (1, 'Mertz',   'Fred') ,(2, 'Doe',     'Jane') ,(3, 'Smith',   'Frank'),(4, 'Ricardo', 'Lucy') ,(5, 'Starr',   'Ringo');


create table stats (member_id int, dates date, stat_id int);
insert into stats values (1, '2017-12-31', 1),(3, '2017-12-31', 2),(4, '2017-12-31', 3),(2, '2018-12-31', 4),(4, '2018-12-31', 5),(2, '2019-05-05', 6),(3, '2019-05-05', 7);



mysql> (select 
    -> m.id,
    -> m.fname,
    -> count(*) as total_days
    -> from 
    -> members m inner join stats s on m.id = s.member_id
    -> group by m.id)
    -> union
    -> (select
    -> m.id,
    -> m.fname,
    -> 0 as total_days
    -> from
    -> members m where not exists ( select * from stats s where m.id = s.member_id));
+----+-------+------------+
| id | fname | total_days |
+----+-------+------------+
|  1 | Fred  |          1 |
|  3 | Frank |          2 |
|  4 | Lucy  |          2 |
|  2 | Jane  |          2 |
|  5 | Ringo |          0 |
+----+-------+------------+
5 rows in set (0.00 sec)

【讨论】:

  • @Strawberry ,你是对的,这完全取决于我们的计数。对于这种情况,我发表了这样的评论。
  • @Strawberry 根据您的建议进行了编辑。你的答案真的更好。我希望我的建议有资格获得投票!
  • 我认为这个答案是基于不正确的分析,所以我希望它不会被赞成。对不起:-(
猜你喜欢
  • 2023-03-15
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多