【问题标题】:PDO select and count IN HAVING DISTINCT to appear in dropdownPDO 选择并计数 IN HAVING DISTINCT 出现在下拉列表中
【发布时间】:2014-01-04 04:19:54
【问题描述】:

我有这个 mysql select 工作得很好。它返回正确的数据。我似乎无法获得正确的上下文来放置 custnum 的实际计数,因此它将出现在下拉选项选择的末尾。 此语句返回正确的位置名称

$statement = $pdo->prepare("SELECT locationname FROM location WHERE locationname IN (SELECT locationname FROM location_user WHERE custnum= :custnum GROUP BY locationname HAVING COUNT( DISTINCT email) < 6 )");
  $statement->execute(array(':custnum' => $session->custnum));

 while($row = $statement->fetch(PDO::FETCH_ASSOC)){
echo'<option value="'.$row['locationname'].'">'.$row['locationname'].'('. $row['COUNT(total)'] .')</option>';    
}

这是我尝试获取每个 custnum 总数的尝试之一

$statement = $pdo->prepare("SELECT locationname, COUNT(custnum) AS total FROM location WHERE  locationname IN (SELECT locationname FROM location_user WHERE custnum= :custnum GROUP BY locationname HAVING COUNT( DISTINCT email) < 6 )");
$statement->execute(array(':custnum' => $session->custnum));

while($row = $statement->fetch(PDO::FETCH_ASSOC)){
echo'<option value="'.$row['locationname'].'">'.$row['locationname'].'('. $row['total'] .')</option>';    
}

这是我的桌子

       table location                            table location_user
custnum   |   locationname             custnum   |    locationname  |   email    |  userlevel
   1           location1                 1            location1       1me@you.com       3
   1           location2                 1            location1       1me@you.com       1
                                         1            location1       2me@you.com       2
                                         1            location1       3me@you.com       2
                                         1            location1       4me@you.com       2
                                         1            location1       5me@you.com       2
                                         1            location2       1me@you.com       2
                                         1            location2       1me@you.com       3

第一个选择返回

 location1()
 location2()

第二次选择返回

 location1(2)

我实际上需要查询正在执行的不同电子邮件的计数,并且只返回表中少于 6 个的不同电子邮件的位置名称,但是我如何获得每个位置名称的不同电子邮件的实际数量。

此选择将检索 DISTINCT 电子邮件的总数,但如何将两者合二为一以用于我的 while 循环?

$statement2 = $pdo->prepare("SELECT COUNT(email) AS total FROM location_user WHERE custnum= :custnum GROUP BY locationname HAVING COUNT( DISTINCT email) < 6");
$statement2->execute(array(':custnum' => $session->custnum));

这是在 Peter 的帮助下和 Tin 的一点刺激下的工作版本。

 $statement = $pdo->prepare("SELECT l.locationname, COUNT(DISTINCT lu.email) AS total 
 FROM location l LEFT JOIN location_user lu ON l.locationname = lu.locationname AND l.custnum = lu.custnum WHERE l.custnum = :custnum GROUP BY l.locationname HAVING COUNT(DISTINCT lu.email)  < 5 ");
 $statement->execute(array(':custnum' => $session->custnum));

 while($row = $statement->fetch(PDO::FETCH_ASSOC)){
 echo'<option value="'.$row['locationname'].'">'.$row['locationname'].'('. $row['total'] .')</option>';    
 }

这是我正在处理的另一个版本,用于跳过将位置添加到表中的用户。此用户的用户级别始终 > 2。用户级别仅作为 1-9 之间的值放置在 location_user 表中。所以我仍然需要位置名称,但我不希望他们的位置包含在计数中。我刚刚意识到我实际上可以走一条更好的路线,因为我想要计算的唯一电子邮件的用户级别为 2。我正在使用不同的电子邮件过滤掉用户级别 1。我会试一试。以下版本删除了我不在 location_user 表中但返回正确计数的位置。

     SELECT l.locationname, COUNT(lu.userlevel) AS total 
     FROM location l LEFT JOIN location_user lu
     ON l.locationname = lu.locationname
     AND l.custnum = lu.custnum
     WHERE l.custnum = :custnum
     AND lu.userlevel = 2
     GROUP BY l.locationname
     HAVING COUNT(lu.userlevel) < 6

【问题讨论】:

  • 你能显示表模式和示例数据吗?
  • 我添加了表格信息和一个将检索电子邮件总数的选择,但我不知道如何将 while 循环组合成一个语句。
  • 您能否根据示例数据显示准确所需的输出?你的解释不清楚。
  • 发布的表数据的所需输出将是 location1(5) 和 location2(1),因为它将 location1 中的两封 1me@you.com 电子邮件视为一个。
  • 谢谢彼得姆,我想这样就可以了。我越来越近了。这些连接看起来有点熟悉。感谢您的所有时间和专业知识。

标签: php mysql sql pdo


【解决方案1】:

UPDATE2: 基于您的 cmets。试试这个方法

SELECT l.locationname, COUNT(DISTINCT lu.email) AS total 
  FROM location l LEFT JOIN location_user lu
    ON l.locationname = lu.locationname
   AND l.custnum = lu.custnum
   AND lu.userlevel < 3 -- consider only users with user level < 3
 WHERE l.custnum = ?
 GROUP BY l.locationname 
HAVING COUNT(DISTINCT lu.email) < 6

样本输出:

|位置名称 |总计 | |--------------|---------| |位置1 | 5 | |位置2 | 1 | |位置3 | 0 |

这里是SQLFiddle演示

【讨论】:

  • 这很好,但如果它们尚未添加到 location_user 表中,我需要它从位置表中提取可用的位置名。这就是我使用 IN 选择的原因。
  • 非常感谢!你解决了我的问题。我对那些参与其中的加入声明感到非常挣扎。它似乎正在做我正在寻找的东西。我得到了字符串以及每个字符串的数量,如果有 6 个则将其删除,因此无法选择。非常棒。对困惑感到抱歉。我将稍微编辑您的代码以使用我的 pdo 变量绑定。
  • 对不起,我完全忘记了我有一个用户正在向表中添加位置,我希望它们从电子邮件计数中跳过。它可以基于用户级别,因为我在 location_user 中有该值。如果用户级别 > 2,我想跳过计算电子邮件。我不确定在哪里附加代码,但会先看看你的代码,然后把它贴在上面。
  • 请查看更新的答案和 sqlfiddle 示例。当使用OUTER JOIN 时,此特定条件应位于ON 子句中。这意味着您要在加入之前过滤 LEFT JOIN 右侧的行。
【解决方案2】:

您实际上不需要从表 location 查询,因为您已经拥有表 location_user 中的 locationname 字段

SELECT locationname, count(DISTINCT email) as total FROM location_user WHERE custnum = :custnum GROUP BY locationname HAVING count(DISTINCT email) < 6

【讨论】:

  • 感谢您的回复。两个表都有 custnum,但我刚刚意识到最后一个版本正在返回正确的值,但这不是我想要的。从现在开始的第一个选择现在在下拉列表中返回两个字符串,但没有总数。第二个返回一个字符串,其中数字为 2。所以我认为它返回的位置总数是两个。我可能需要调整我的桌子。
  • 在这种情况下,我认为您需要在查询末尾使用 GROUP BY locationname ,您将再次在下拉列表中获得两个字符串。
  • 我用 INNER JOIN 尝试了上面的选择,它返回的结果与我上面发布的第二个选择相同。
  • 好的,我需要再次查看我的代码。我在位置表中添加了另一个位置名称,但没有得到我想的结果。我以为我的工作正常,所以选择只会显示 location_user 表中位置表中的位置名称少于 6 次。
  • 看看彼得的另一个答案,他明白了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 2022-07-28
相关资源
最近更新 更多