使用JOIN从2个表中进行选择,并将一个表中的列值与另一表的计数进行比较

时间:2018-10-09 19:39:26

标签: mysql

我正在尝试使用JOIN从2个表中进行选择:

SELECT a.*, COUNT(b.*) as num_topups FROM customer_sms a JOIN customer_sms_topups b ON a.sequence = b.sms_account WHERE a.sequence = b.sms_account AND a.auto_topup_credits > '0' AND a.auto_topup_threshold <= a.balance AND MONTH(b.datetime) = '10' AND YEAR(b.datetime) = '2018' AND num_topups < a.auto_topup_maximum;

但是我想我算错了:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*) as num_topups FROM customer_sms a JOIN customer_sms_topups b ON a.sequence = ' at line 1

我需要计数才能将customer_sms_topups中的行数与a.auto_topup_maximum

进行比较

2 个答案:

答案 0 :(得分:1)

对于计数,应使用count(*)

但是您在select中有其他列未参与聚合功能,并且在group by中未提及
在SQL中已弃用此功能,在大多数数据库中均不起作用,在最新版本的mysql中dpn不起作用

适用于该版本的版本,此列的结果无法预测
所以你应该 或在select中使用显式列名称并添加适当的group by子句,例如:

SELECT a.col1
      , a.col2  
        , COUN(T*) as num_topups 
FROM customer_sms a 
JOIN customer_sms_topups b ON a.sequence = b.sms_account 
WHERE a.sequence = b.sms_account 
AND a.auto_topup_credits > '0' 
AND a.auto_topup_threshold <= a.balance 
AND MONTH(b.datetime) = '10' 
AND YEAR(b.datetime) = '2018'
group by a.col1 , a.col2   

或对您选择的所有列使用聚合功能

SELECT min(a.col1)
      , min(a.col2  )
        , COUNT(*) as num_topups 
FROM customer_sms a 
JOIN customer_sms_topups b ON a.sequence = b.sms_account 
WHERE a.sequence = b.sms_account 
AND a.auto_topup_credits > '0' 
AND a.auto_topup_threshold <= a.balance 
AND MONTH(b.datetime) = '10' 
AND YEAR(b.datetime) = '2018'

答案 1 :(得分:0)

可以在HAVING子句中对聚合表达式进行比较,但在WHERE子句中则不允许。

通常,在带有聚合的查询中,我们通常有一个GROUP BY子句,除非我们希望将结果折叠成一行。

没有实际的说明(如示例数据和预期结果所示),我们只是猜测查询应返回什么结果。

我的猜测是我们正在寻找该查询将返回的结果:

SELECT a.*
     , COUNT(b.sms_account) AS num_topups
  FROM customer_sms a

  LEFT
  JOIN customer_sms_topups b
    ON b.sms_account = a.sequence
   AND b.datetime   >= '2018-10-01' 
   AND b.datetime    < '2018-10-01' + INTERVAL 1 MONTH

 WHERE a.auto_topup_credits > '0'
   AND a.auto_topup_threshold <= a.balance

 GROUP
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...

HAVING COUNT(b.sms_account) < a.auto_topup_maximum

 ORDER
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...

如果我们要排除num_topups具有“零”的行,则可以删除LEFT关键字。

还有其他几种查询模式可以返回等效结果。

例如,条件聚合:

SELECT a.*
     , SUM(IF(b.datetime >= '2018-10-01' AND b.datetime < '2018-10-01' + INTERVAL 1 MONTH
           ,1,0)
       ) AS num_topups
  FROM customer_sms a
  LEFT
  JOIN customer_sms_topups b
    ON b.sms_account = a.sequence
 WHERE a.auto_topup_credits > '0'
   AND a.auto_topup_threshold <= a.balance

 GROUP
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...

HAVING num_topups < a.auto_topup_maximum

 ORDER
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...

或者我们可以在内联视图中进行聚合,然后进行联接。使用这种模式,我们可以避免在外部查询上使用GROUP BY子句。

SELECT a.*
     , c.num_topups
  FROM customer_sms a
  LEFT
  JOIN ( SELECT b.sms_account   AS sms_account
              , SUM(1)          AS num_topups
           FROM customer_sms_topups b
          WHERE b.datetime   >= '2018-10-01' 
            AND b.datetime    < '2018-10-01' + INTERVAL 1 MONTH
          GROUP
             BY b.sms_account
       ) c
    ON c.sms_account = a.sequence
   AND IFNULL(c.num_topups,0) < a.auto_topup_maximum

 WHERE a.auto_topup_credits > '0'
   AND a.auto_topup_threshold <= a.balance

 ORDER
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...

SELECT列表中的相关子查询也可以用于获取计数。通过避免联接到子表,我们可以在外部查询中不需要GROUP BY子句的情况下获得相关行的计数:

SELECT a.*
     , ( SELECT COUNT(1) 
           FROM customer_sms_topups b
          WHERE b.sms_account = a.sequence 
            AND b.datetime   >= '2018-10-01' 
            AND b.datetime    < '2018-10-01' + INTERVAL 1 MONTH
       ) AS num_topups
  FROM customer_sms a
 WHERE a.auto_topup_credits > '0'
   AND a.auto_topup_threshold <= a.balance

HAVING num_topups < a.auto_topup_maximum

 ORDER
    BY a.sequence
     , a.auto_topup_credits
     , a.auto_topup_threshold
     , a.balance
     , ...