好的,我试图计算一个月内购买东西的用户,但是在之前几个月的任何一天都没有买过东西(比如,确定有多少新用户是每个月都有),所以这就是我有点想做的事情,但它显然不起作用:
SELECT COUNT(DISTINCT user_id NOT IN (
SELECT user_id
FROM payment
WHERE amount > 0
AND MONTH(payment_date) < "10"
GROUP BY user_id
) AS new_users_count
FROM payment
WHERE amount > 0
AND MONTH(payment_date) >= "10"
如果我使用&#34; DISTINCT&#34;它返回0计数。
如果我把它拿出来,它会返回所有新老用户。
另外,在COUNT()中使用子查询需要一段时间来处理。
任何方式都可以使用SUM(IF ...)来完成?还是其他更优化的方式?
我到处寻找一个想法/解决方案,只是无法弄清楚。
答案 0 :(得分:0)
将标准放在WHERE子句中。使用curl
或curl -v -X COPY http://localhost:8080/method
。
NOT EXISTS
以下是条件聚合的替代方法:
NOT IN
答案 1 :(得分:0)
使用NOT EXISTS
验证前一个月内同一用户不存在付款。
SELECT COUNT(DISTINCT tm.USERID)
FROM payment tm
WHERE tm.amount > 0
AND MONTH(tm.payment_date) >= "10"
AND NOT EXISTS
( SELECT 'x'
FROM payment lm
WHERE lm.amount > 0
AND MONTH(lm.payment_date) < "10"
AND lm.user_id = tm.user_id
)
PS:请注意,此查询一旦成为2016年将不再有效!以下是对此的修复。它交叉加入计算以获得该月的第一天。该值(DATEPIVOT)用于在当天或之前获得付款。为了计算,我使用了answer by Aleroot。
这种表示法的另一个优点是,MySQL应该能够更好地利用payment.payment_date上的任何索引,因此当您的数据变大时,此查询将受到性能下降的影响。
SELECT COUNT(DISTINCT tm.USERID)
FROM payment tm
CROSS JOIN
(SELECT
DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY) as DATEPIVOT) d
WHERE tm.amount > 0
AND tm.payment_date >= d.DATEPIVOT
AND NOT EXISTS
( SELECT 'x'
FROM payment lm
WHERE lm.amount > 0
AND lm.payment_date < d.DATEPIVOT
AND lm.user_id = tm.user_id
)
答案 2 :(得分:0)
COUNT(DISTINCT user_id NOT IN (..something..)
被理解为
COUNT(DISTINCT (user_id NOT IN (..something..))
和NOT IN
是一个布尔运算符,返回true / false(= 1/0)
COUNT()
中的条件没有意义 - 您可能希望在WHERE
子句中执行此操作。或者您可以使用SUM()
和GROUP BY
。
但是根本不使用子查询通常会更好(MySQL 5.6+可以很好地处理子查询,但是你的是#34;依赖&#34;一个)。这样的事情应该有效:
SELECT COUNT(DISTINCT p1.user_id)
FROM payment p1
LEFT JOIN payment p2
ON p1.user_id = p2.user_id
AND p2.amount > 0
AND MONTH(p2.payment_date) < 10
WHERE p1.amount > 0
AND MONTH(p1.payment_date) >= 10
AND p2.user_id IS NULL;
左连接将加入相同user_id的任何现有行,该用户在&#34;之前订购了某些内容&#34;所以您只需与p2.user_id IS NULL
核实没有这样的&#34;之前的订单&#34;存在此user_id。然后计算结果 - 因为每个用户可以多次返回,具体取决于付款次数,DISTINCT
负责处理。
一些注释
MONTH(datetime)
返回号码,因此删除了10
user_id
上的索引才能使其在任何合理的时间内正常工作,最好是(user_id, amount, payment_date)
上的综合索引将其转换为联接的索引扫描MONTH(p1.payment_date) >= 10
不是可转化的条件,而且它明年会发生变化,因此您应该在比较中使用完整日期,例如p1.payment_date >= '2015-10-01'
(p2
也是如此})然后在(payment_date, user_id, amount)
上添加一个索引,以便快速FROM
部分(只有至少有#34;新&#34;付款的用户将被检查,没有活动的旧用户将不会一直都要重新检查。)答案 3 :(得分:-1)
我不确定但为什么不在SELECT之后使用DISTINCT?
SELECT DISTINCT COUNT(user_id NOT IN