两张桌子
表1 - 客户表
user_id Name
1 first
2 Second
表2 - customer_activity表
user_id type
1 downloaded_software
1 filled_download_form
2 downloaded_software
2 filled_download_form
2 purchased
目标 - 选择已下载软件,fill_download_form并购买的所有客户。
我的查询
SELECT SQL_CALC_FOUND_ROWS DISTINCT(c.user_id)
FROM customer AS c
INNER JOIN customer_activity AS ca ON ca.user_id = c.user_id
WHERE ca.type IN('downloaded_software','filled_download_form','purchased')
ORDER BY c.user_id asc
LIMIT 0, 100
结果
1
2
期望的结果
2
修改 评论摘要:
这个问题的答案如下,但可能的好方案是从列表中排除一些项目。 例如,如果我想搜索已下载软件,fill_software_form但未购买的客户。
@Serpiton在评论中的fiddle中回答了这个问题。
答案 0 :(得分:2)
您可以按user_id
进行分组,并计算type
的不同值。由于WHERE将值限制为仅3可能,因此如果找到所有值,则不同值的计数应为3;
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
JOIN customer_activity AS ca ON ca.user_id = c.user_id
WHERE ca.type IN('downloaded_software', 'filled_download_form', 'purchased')
GROUP BY c.user_id
HAVING COUNT(DISTINCT ca.type) = 3
ORDER BY c.user_id
LIMIT 0, 100
编辑:要从评论中回答您的问题,如果您需要排除类型,则无法轻松使用GROUP BY来查找结果。您可以为每种类型执行自联接(左联接已排除的联接并检查它是否导致无行);
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
JOIN customer_activity AS ca1
ON ca1.user_id = c.user_id AND ca1.type = 'downloaded_software'
JOIN customer_activity AS ca2
ON ca2.user_id = c.user_id AND ca2.type = 'filled_download_form'
LEFT JOIN customer_activity AS ca3
ON ca3.user_id = c.user_id AND ca3.type = 'purchased'
WHERE ca3.user_id IS NULL
ORDER BY c.user_id
LIMIT 0, 100
...或 - 如果您自动生成查询,效率不高但可能更容易 - 您可以使用IN
和NOT IN
使用3个简单子查询来选择类型是否应该是包含与否......
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
WHERE c.user_id IN (
SELECT user_id FROM customer_activity WHERE type='downloaded_software'
) AND c.user_id IN (
SELECT user_id FROM customer_activity WHERE type='filled_download_form'
) AND c.user_id NOT IN (
SELECT user_id FROM customer_activity WHERE type='purchased'
)
ORDER BY c.user_id
LIMIT 0,100;
答案 1 :(得分:1)
免责声明:在Joachim Isaksson回答的评论中我建议对OP的一个问题进行修改,OP要求澄清,就是这样。
从带有修改的查询开始
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
JOIN customer_activity AS ca
ON ca.user_id = c.user_id
WHERE ca.type IN('downloaded_software',
'filled_download_form',
'purchased')
GROUP BY c.user_id
HAVING COUNT(DISTINCT ca.type) = 2
AND COUNT(CASE WHEN ca.type = 'purchased' THEN 1 ELSE NULL END) = 0
ORDER BY c.user_id
LIMIT 0, 100
粗体部分是我建议的编辑。
如果在我修改过的部分之外不清楚你应该问Joachim Isaksson,因为他是编写查询的人。
我的编辑按照它的说法执行:第一个条件检查type
的三个有效值中只有两个,第二个检查“已购买”是否为遗漏。第二个条件相当于
SUM(CASE WHEN ca.type = 'purchased' THEN 1 ELSE 0 END) = 0
这可能更简单易读。
整个查询等同于
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
JOIN customer_activity AS ca
ON ca.user_id = c.user_id
WHERE ca.type IN('downloaded_software',
'filled_download_form',
'purchased')
GROUP BY c.user_id
HAVING COUNT(DISTINCT
CASE WHEN ca.type = 'downloaded_software' THEN 1 ELSE NULL END) = 1
AND COUNT(DISTINCT
CASE WHEN ca.type = 'filled_download_form' THEN 1 ELSE NULL END) = 1
AND COUNT(DISTINCT
CASE WHEN ca.type = 'purchased' THEN 1 ELSE NULL END) = 0
ORDER BY c.user_id
LIMIT 0, 100
(如果您只有这3种类型,则不需要WHERE
)
如果您是从编程语言编写查询,我将使用它作为模板
SELECT SQL_CALC_FOUND_ROWS c.user_id
FROM customer AS c
JOIN customer_activity AS ca
ON ca.user_id = c.user_id
WHERE ca.type IN('downloaded_software',
'filled_download_form',
'purchased')
GROUP BY c.user_id
HAVING COUNT(DISTINCT
CASE WHEN ca.type = 'downloaded_software'
THEN 1 ELSE NULL END) = ?downloaded?
AND COUNT(DISTINCT
CASE WHEN ca.type = 'filled_download_form'
THEN 1 ELSE NULL END) = ?filled?
AND COUNT(DISTINCT
CASE WHEN ca.type = 'purchased'
THEN 1 ELSE NULL END) = ?purchased?
ORDER BY c.user_id
LIMIT 0, 100
以?downloaded?
,?filled?
和?purchased?
作为参数。 1表示需要存在类型,0表示该参数需要丢失
回答另一个问题例如,仅针对既没有fill_download_form也没有购买的客户。对此的查询是什么?只是相应地填充参数。