SQL 个使用自联接的查询
SQL queries using self-join
我可以进行简单的 select、加入、更新查询。但这对我来说似乎有点难(我只是在学习)。
客户有这样的 table(使用 Mysql)(我无法控制他的数据库架构,我无法创建a Customers table 给他。我只需要创建一些客户报告)。
+-----------+--------------+--------------------------+
|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) AND 搜索(如 'blue' AND 'green')
已购买 'this' 和 'that' 套装的客户。
我需要得到这样的结果:
|John | jo@gmail.com |
或者这个(正如我所说,John 可以在每次交易中以不同的方式输入他的名字。如果电子邮件是唯一的,那很好):
|JOHN G. | jo@gmail.com |
2) 或搜索(如 'blue' 或 'red')
需要得到这个:
|John | jo@gmail.com |
|Paul | pa@gmail.com |
或者这个:
|John | jo@gmail.com |
|Paul Simon| pa@gmail.com |
3) 买了一套,但没买另一套(喜欢 'green' 但不喜欢 'blue')
|Mary | ma@gmail.com |
有人知道怎么做吗?我相信这可以通过某种 'self join' 来实现。但由于我只是一个初学者,我不知道如何解决这个问题。
对于第一个查询 - 我在这里使用子查询
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 条记录并且该记录应该具有输入中提到的设置值)
select * from customer group by email having count(pset)= 1 and pset like 'green';
显然一个人可以买这套或那套,我想一个人甚至有可能在以后的交易中再次购买同一套。
所以你想要每个人的信息。最简单的方法是通过按人分组 (GROUP BY
) 来汇总您的数据。然后检查 HAVING
子句中的聚合:Did the customer by set X and/or 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
.
我可以进行简单的 select、加入、更新查询。但这对我来说似乎有点难(我只是在学习)。
客户有这样的 table(使用 Mysql)(我无法控制他的数据库架构,我无法创建a Customers table 给他。我只需要创建一些客户报告)。
+-----------+--------------+--------------------------+
|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) AND 搜索(如 'blue' AND 'green') 已购买 'this' 和 'that' 套装的客户。 我需要得到这样的结果:
|John | jo@gmail.com |
或者这个(正如我所说,John 可以在每次交易中以不同的方式输入他的名字。如果电子邮件是唯一的,那很好):
|JOHN G. | jo@gmail.com |
2) 或搜索(如 'blue' 或 'red') 需要得到这个:
|John | jo@gmail.com |
|Paul | pa@gmail.com |
或者这个:
|John | jo@gmail.com |
|Paul Simon| pa@gmail.com |
3) 买了一套,但没买另一套(喜欢 'green' 但不喜欢 'blue')
|Mary | ma@gmail.com |
有人知道怎么做吗?我相信这可以通过某种 'self join' 来实现。但由于我只是一个初学者,我不知道如何解决这个问题。
对于第一个查询 - 我在这里使用子查询
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 条记录并且该记录应该具有输入中提到的设置值)
select * from customer group by email having count(pset)= 1 and pset like 'green';
显然一个人可以买这套或那套,我想一个人甚至有可能在以后的交易中再次购买同一套。
所以你想要每个人的信息。最简单的方法是通过按人分组 (GROUP BY
) 来汇总您的数据。然后检查 HAVING
子句中的聚合:Did the customer by set X and/or 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
.