mysql学习—自连接的用法

1-2 自连接的用法

可重排列、排列、组合

应用场景:假设一张存放了商品名称及价格的表,表里有“苹果、橘子、香蕉”三条记录。在生成用于查询销售额的报表时,需要获取这些商品的组合。
组合:分为有顺序的有序对 <1,2> 和 无顺序的无序对 {1,2}。分别对应“排列”和“组合”
(1)可重排列
通过交叉连接生成笛卡尔积,可以得到有序对

/* 用于获取可重排列的SQL语句 */
SELECT P1.name AS name_1, P2.name AS name_2
  FROM Products P1, Products P2;

(2)排列
去掉由相同元素构成的对。

/* 用于获取排列的SQL语句 */
SELECT P1.name AS name_1, P2.name AS name_2
  FROM Products P1, Products P2
 WHERE P1.name <> P2.name;

(3)组合
对调换了元素顺序的对进行去重

/* 用于获取组合的SQL语句 */
SELECT P1.name AS name_1, P2.name AS name_2
FROM Products P1, Products P2
WHERE P1.name > P2.name;

若想要获取3个以上元素的组合,只需要简单扩展一下即可

/* 用于获取组合的SQL语句:扩展成3列时 */
SELECT P1.name AS name_1, P2.name AS name_2, P3.name AS name_3
  FROM Products P1, Products P2, Products P3
WHERE P1.name > P2.name
  AND P2.name > P3.name;

删除重复行

(1)使用极值函数

/* 用于删除重复行的SQL语句(1):使用极值函数 */
DELETE FROM Products P1
 WHERE rowid < ( SELECT MAX(P2.rowid)
                   FROM Products P2
                  WHERE P1.name = P2. name
                    AND P1.price = P2.price ) 

SQL中赋予不同名称的集合,我们应该将其看作不同的集合,这个子查询会比较P1、P2,然后返回商品名称和价格都相同的行里最大的rowid所在的行。
(2)使用非等值连接

/* 用于删除重复行的SQL语句(2):使用非等值连接 */
DELETE FROM Products P1
 WHERE EXISTS ( SELECT *
                  FROM Products P2
                 WHERE P1.name = P2.name
                   AND P1.price = P2.price
                   AND P1.rowid < P2.rowid );

查找局部不一致的列

场景:查找“同一家人但是住址不同的记录”
自连接与非等值连接结合

/* 用于查找是同一家人但住址却不同的记录的SQL语句 */
SELECT DISTINCT A1.name, A1.address
  FROM Addresses A1, Addresses A2
 WHERE A1.family_id = A2.family_id
   AND A1.address <> A2.address ;

问题:查找价格相等的商品组合
思路:
家庭——>价格
住址——>商品名称

排序

应用场景:在使用数据库制作各种票据和统计表工作中,会经常遇到按分数、人数或者销售额等数值进行排序的需求。(Oracle 、DB2 数据库的rank函数)
(1)使用窗口函数

/* 排序:使用窗口函数 */
SELECT name, price,
       RANK() OVER (ORDER BY price DESC) AS rank_1,
       DENSE_RANK() OVER (ORDER BY price DESC) AS rank_2
  FROM Products;

出现相同位次后,rank_1跳过之后的位次,rank_2没有跳过,而是连续排序。
(2)SQL 和 集合论的关系

/* 排序从1开始。如果已出现相同位次,则跳过之后的位次 */
SELECT P1.name,
       P1.price,
      (SELECT COUNT(P2.price)
         FROM Products P2
        WHERE P2.price > P1.price) + 1 AS rank_1
 FROM Products P1
 ORDER BY rank_1;
/* 排序从1开始,连续输出位次 */
SELECT P1.name,
       P1.price,
      (SELECT COUNT( DISTINCT P2.price)
         FROM Products P2
        WHERE P2.price > P1.price) + 1 AS rank_1
 FROM Products P1
 ORDER BY rank_1;

执行原理:面向集合的思维方式。子查询所做的,是计算出价格比自己高的记录并将其作为自己的位次。

集合 价格 比自己高的价格 位次
S0 100 0
S1 80 100 1
S1 50 100,80 2
S2 30 100,80,50 3

0=空
1={0}
2={0,1}
3={0,1,2}

(3)使用自连接

/* 排序:使用自连接 */
SELECT P1.name,
       MAX(P1.price) AS price,
       COUNT(P2.name) +1 AS rank_1
  FROM Products P1 LEFT OUTER JOIN Products P2
    ON P1.price < P2.price
 GROUP BY P1.name
 ORDER BY rank_1;

猜你喜欢

转载自blog.csdn.net/weixin_43387060/article/details/86176023