多个表MySQL的结果

时间:2014-06-17 04:06:06

标签: mysql sql join

两张桌子

表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中回答了这个问题。

2 个答案:

答案 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

An SQLfiddle to test with

编辑:要从评论中回答您的问题,如果您需要排除类型,则无法轻松使用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

...或 - 如果您自动生成查询,效率不高但可能更容易 - 您可以使用INNOT 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;

An SQLfiddle showing both in action

答案 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也没有购买的客户。对此的查询是什么?只是相应地填充参数。