使用自联接的SQL查询

时间:2016-04-09 09:27:33

标签: mysql sql self-join

我可以简单地选择,加入,更新查询。但这对我来说似乎有点困难(我只是在学习)。

客户有一个这样的表(使用 Mysql )(我无法控制他的数据库架构,我无法为他创建一个Customers表。我只需要创建一些客户的报告)。

+-----------+--------------+--------------------------+
|Transaction|Customers name|Customers email   |Set    |
+-----------+--------------+--------------------------+
| 1         | John         | jo@gmail.com     | blue  |
| 2         | Mary         | ma@gmail.com     | green |
| 3         | Paul         | pa@gmail.com     | red   |
| 4         | JOHN G.      | jo@gmail.com     | green |
| 5         | Paul Simon   | pa@gmail.com     | blue  |
+-----------+--------------+--------------------------+

如您所见,客户自愿输入的每笔交易都是他的名字。这可能会导致更多的客户,但电子邮件领域是独一无二的。

我需要制作这些报告(所有这些都是由他买的东西驱动的 - 'Set'字段):

1)并搜索(例如'blue'和'green') 已购买'此'和'那'设置的客户。 我需要得到这样的结果:

|John      | jo@gmail.com |

或者这(就像我说的那样,约翰可以在每次交易时以不同的方式输入他的名字。如果电子邮件是唯一的,那就没关系了):

|JOHN G.   | jo@gmail.com |

2)或搜索(如“蓝色”或“红色”) 需要得到这个:

|John      | jo@gmail.com | 
|Paul      | pa@gmail.com |

或者这个:

|John      | jo@gmail.com | 
|Paul Simon| pa@gmail.com |

3)买了一套,但不买另一套(比如'绿色'但不是'蓝色')

|Mary      | ma@gmail.com |

Doe有谁知道怎么做?我相信这可以通过某种“自我加入”来实现。但由于我只是一个初学者,我无法弄清楚如何解决这个问题。

2 个答案:

答案 0 :(得分:1)

对于第一个查询 - 我在这里使用子查询

select name,email from customer c where Set = 'blue' and c.email = (select email from customer where Set = 'green' and email = c.email);

对于第二个查询 - 简单或条件就足够了

select * from customer where Set = 'green' or Set = 'blue' group by email  ;

对于第三个查询 - (根据您的要求,它可以工作,它基于类似于应该只有1个记录的方法,并且该记录应该具有输入中提到的Set值)

select * from customer group by email having count(pset)= 1 and pset like 'green';

答案 1 :(得分:1)

显然,一个人可以购买这套或那套,我想甚至有可能一个人在以后的交易中再购买同一套。

所以你想要每个人的信息。最简单的方法是通过按人分组(GROUP BY)来汇总数据。然后检查HAVING子句中的聚合:客户是否按设置X和/或y?

查询1:

select email, name
from transactions
group by email
having max(case when set = 'blue' then 1 else 0 end) = 1
   and max(case when set = 'green' then 1 else 0 end) = 1;

查询2:

select email, name
from transactions
group by email
having max(case when set = 'blue' then 1 else 0 end) = 1
    or max(case when set = 'red' then 1 else 0 end) = 1;

查询3:

select email, name
from transactions
group by email
having max(case when set = 'green' then 1 else 0 end) = 1
   and max(case when set = 'blue' then 1 else 0 end) = 0;

您使用这些查询获得的名称只是任意选择的匹配名称之一。这在MySQL中很特别。在标准SQL中,这是不允许的。无论如何,无论是MySQL还是标准SQL,您还可以使用MIN(name)MAX(name)始终按字母顺序获取第一个或最后一个。

顺便说一句:CASE WHEN表达式是标准SQL。然而,MySQL具有一个额外的特殊布尔处理:真实表达式的计算结果为1,假表达式为0.因此,在MySQL中,您只需编写max(set = 'green') = 1而不是max(case when set = 'green' then 1 else 0 end) = 1

相关问题