zoukankan      html  css  js  c++  java
  • 自连接用法

    可重排列、排列、组合

    CREATE TABLE Products
    (name VARCHAR(16) PRIMARY KEY,
     price INTEGER NOT NULL);
     
    INSERT INTO Products VALUES('苹果',	50);
    INSERT INTO Products VALUES('橘子',	100);
    INSERT INTO Products VALUES('香蕉',	80);
    
    用于获取可重排列的SQL 语句
    SELECT P1.name AS name_1, P2.name AS name_2
    FROM Products P1, Products P2
    -- 也可写作:
    SELECT P1.name AS name_1, P2.name AS name_2
    FROM Products P1 CROSS JOIN Products P2;
    

    执行结果里每一行(记录)都是一个有序对。因为是可重排列,所以结果行数为 3^2 = 9

    排除掉由相同元素构成的对:
    SELECT P1.name AS name_1, P2.name AS name_2
    FROM Products P1, Products P2
    WHERE P1.name <> P2.name;
    

    排除掉由相同元素构成的对,结果行数为6排列 。
    在 SQL 里,只要被赋予了不同的名称,
    即便是相同的表也应该当作不同的表(集合)来对待。所以,相同的表的自连接和不同表间的普通连接并没有什么区别。

    接下来我们进一步对(苹果, 橘子)和(橘子, 苹果)这样只是调换了元素顺序的对进行去重:
    SELECT P1.name AS name_1, P2.name AS name_2
    FROM Products P1, Products P2
    WHERE P1.name > P2.name;
    

    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;
    

    在加上“不等于”这个条件后,这条SQL语句所做的是,按字符顺序排列各商品,只与“字符顺序比自己靠前”的商品进行配对

    删除重复行

    如果重复的列里不包含主键,就可以用主键来处理,但像这道例题一样所有的列都重复的情况,则需要使用由数据库独自实现的行 ID。如果重复的列里不包含主键,就可以用主键来处理,如果所有的列都重复的情况,则需要使用由数据库独自实现的行 ID。
    (给用户提供了可用的行 ID 的数据库只有 Oracle(rowid )和 PostgreSQL(oid
    ))。

    -- 用于删除重复行的SQL语句:使用极值函数  
    DELETE FROM Products P1 WHERE rowid < ( SELECT MAX(P2.rowid)
    FROM Products P2 WHERE P1.name = P2. name AND P1.price = P2.price );
    
    -- 用于删除重复行的SQL语句:使用非等值连接  
    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 P1.name, P1.price
    FROM Products P1, Products P2
    WHERE P1.price = P2.price
    AND P1.name <> P2.name;
    

    排序

    在使用数据库制作各种票据和统计表的工作中,我们经常会遇到按分数、人数或销售额等数值进行排序的需求。
    要按照价格从高到低的顺序,对商品进行排序:

    DELETE FROM Products;
    INSERT INTO Products VALUES('苹果',	50);
    INSERT INTO Products VALUES('橘子',	100);
    INSERT INTO Products VALUES('葡萄',	50);
    INSERT INTO Products VALUES('西瓜',	80);
    INSERT INTO Products VALUES('柠檬',	30);
    INSERT INTO Products VALUES('香蕉',	50);
    
    -- 窗口函数
    select name,price,
    	RANK() OVER (ORDER BY price DESC) AS rank_1,
    	DENSE_RANK() OVER (ORDER BY price DESC) AS rank_2
    FROM Products;
    

    执行结果:

    name price rank_1 rank_2
    橘子 100 1 1
    西瓜 80 2 2
    苹果 50 3 3
    香蕉 50 3 3
    葡萄 50 3 3
    柠檬 30 6 4
    • 聚合函数RANK和dense_rank主要的功能是计算一组数值中的排序值。
    • 区别:dence_rank在并列关系是,相关等级不会跳过。rank则跳过。

    MySQL暂不支持rank()函数,可以使用非等值自连接:

    -- 排序从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;
    -- 子查询所做的,是计算出价格比自己高的记录的条数并将其作为自己的位次
    

    如果修改成COUNT(DISTINCT P2.price) ,那么存在相同位次的记录时,就可以不跳过之后的位次,而是连续输出(相当于 DENSE_RANK 函数)

    与多表之间进行的普通连接相比,自连接的性能开销更大(特别是与非等值连接结合使用的时候),因此用于自连接的列推荐使用主键或者在相关列上建立索引。
  • 相关阅读:
    内核参数优化/etc/sysctl.conf
    python
    2014又一次认识我
    Android核心服务解析篇(三)——Android系统的启动
    Cocos2d-x 3.0 Android改动APK名、更改图标、改动屏幕方向、改动版本,一些须要注意的问题
    算术表达式
    数学之路-python计算实战(18)-机器视觉-滤波去噪(双边滤波与高斯滤波 )
    交叉排序
    iOS AES的加密解密
    codeforces 570 D Tree Requests
  • 原文地址:https://www.cnblogs.com/sanzashu/p/10997699.html
Copyright © 2011-2022 走看看