zoukankan      html  css  js  c++  java
  • Having子句用法

    Having基础用法

    集合结果指定条件
    注:HAVING子句中能够使用三种要素:常数,聚合函数,GROUP BY子句中指定的列名(聚合建)
    HAVING子句:
    用having就一定要和group by连用, 用group by不一有having(它只是一个筛选条件用的)

    商品品种分组后结果中筛选出数据行数为2行的数据:
    SELECT product_type, COUNT(*)
        FROM Product
      GROUP BY product_type
     HAVING COUNT(*) = 2;
    
    平均数,销售价格大于2500的
    SELECT product_type, AVG(sale_price)
    	FROM Product
     GROUP BY product_type
    HAVING AVG(sale_price) >= 2500;	
    

    相对于HAVING子句,更适合写再Where子句中的条件:

    • where子句 = 指定行所对应的条件
    • having子句 = 指定组所对应的条件
      聚合建所对应的条件不应该书写在HAVING子句中,而应书写在WHERE子句当中。虽执行结果一样,但将条件写在where子句中比写在having子句中的处理速度更快,返回结果时间更短。
      原因:聚合操作时,DBMS内部会进行排序处理,where在排序之前就对数据进行过滤,having是在排序之后在对数据进行分组。
    -- 先过滤后分组
    SELECT product_type, COUNT(*)
    	FROM Product
     GROUP BY product_type
    HAVING product_type = '衣服';
    
    -- 先分组后过滤(性能差点)
    SELECT product_type, COUNT(*)
    	FROM Product
    WHERE product_type = '衣服'
     GROUP BY product_type;
    

    寻找缺失编号

    seq name
    1 小明
    2 小红
    3 小王
    5 小李
    6 小黄
    8 小小
    -- 查看是否存在缺失编号
    SELECT '存在缺失的编号' AS gap
    FROM SeqTbl
    HAVING COUNT(*) <> MAX(seq);
    
    -- 查询缺失编号的最小值
    SELECT MIN(seq + 1) AS ga 
    FROM SeqTbl 
    WHERE (seq+ 1) NOT IN ( SELECT seq FROM SeqTbl)
    

    如果表 SeqTbl 里包含 NULL ,那么这条 SQL 语句的查询结果就不正确了(因为null值表示不确定)

    用 HAVING 子句进行子查询:求众数

    平均值有一个缺点,那就是很容易受到离群值(outlier)的影响。这种时候就必须使用更能准确反映出群体趋势的指标——众数(mode)就是其中之一。它指的是在群体中出现次数最多的值

    CREATE TABLE Graduates
    (name   VARCHAR(16) PRIMARY KEY,
     income INTEGER NOT NULL);
    -- 桑普森是个离群值,会拉高平均数
    INSERT INTO Graduates VALUES('桑普森', 400000);
    INSERT INTO Graduates VALUES('迈克',     30000);
    INSERT INTO Graduates VALUES('怀特',   20000);
    INSERT INTO Graduates VALUES('阿诺德', 20000);
    INSERT INTO Graduates VALUES('史密斯',     20000);
    INSERT INTO Graduates VALUES('劳伦斯',   15000);
    INSERT INTO Graduates VALUES('哈德逊',   15000);
    INSERT INTO Graduates VALUES('肯特',     10000);
    INSERT INTO Graduates VALUES('贝克',   10000);
    INSERT INTO Graduates VALUES('斯科特',   10000);
    
    -- 众数的SQL 语句(1):使用谓词
    SELECT income, COUNT(*) AS cnt 
    FROM Graduates 
    GROUP BY income HAVING COUNT(*) >= ALL ( SELECT COUNT(*) FROM Graduates GROUP BY income)
    

    ALL 谓词用于 NULL 或空集时会出现问题,可以用极值函数来代替

    -- 求众数的SQL 语句(2) :使用极值函数
    SELECT income, COUNT(*) AS cnt 
    FROM Graduates 
    GROUP BY incomeHAVING COUNT(*) >= ( SELECT MAX(cnt)	  
                                        FROM ( SELECT COUNT(*) AS cnt  
                                               FROM Graduates   
                                               GROUP BY income) TMP )
    

    用 HAVING 子句进行自连接:求中位数

    中位数:统计学中的专有名词,代表一个样本、种群或概率分布中的一个数值,其可将数值集合划分为相等的上下两部分。

    -- 将集合里的元素按照大小分为上半部分和下半部分两个子集,同时让这 2 个子集共同拥有集合正中间的元素
    SELECT T1.income FROM Graduates T1, Graduates T2 GROUP BY T1.income
    		HAVING SUM(CASE WHEN T2.income >= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2
               AND SUM(CASE WHEN T2.income <= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2 
               
    -- 将上下部分集合平均然后得中值
     SELECT AVG(DISTINCT income) FROM (
    SELECT T1.income FROM Graduates T1, Graduates T2 GROUP BY T1.income
    				HAVING SUM(CASE WHEN T2.income >= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2
               AND SUM(CASE WHEN T2.income <= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2 ) TMP;
    

    查询不包含 NULL 的集合

    COUNT()和COUNT(列)的区别:
    第一个是性能上的区别;
    第二个是 COUNT(
    )可以用于NULL,而COUNT(列名)与其他聚合函数一样,要先排除掉NULL 的行再进行统计。

    CREATE TABLE Students
    (student_id   INTEGER PRIMARY KEY,
     dpt          VARCHAR(16) NOT NULL,
     sbmt_date    DATE);
    
    INSERT INTO Students VALUES(100,  '理学院',   '2005-10-10');
    INSERT INTO Students VALUES(101,  '理学院',   '2005-09-22');
    INSERT INTO Students VALUES(102,  '文学院',   NULL);
    INSERT INTO Students VALUES(103,  '文学院',   '2005-09-10');
    INSERT INTO Students VALUES(200,  '文学院',   '2005-09-22');
    INSERT INTO Students VALUES(201,  '工学院',   NULL);
    INSERT INTO Students VALUES(202,  '经济学院', '2005-09-25');
    
    -- 查询“提交日期”列内不包含NULL 的学院(1) :使用COUNT 函数
    SELECT dpt
    FROM Students
    GROUP BY dpt
    HAVING COUNT(*) = COUNT(sbmt_date); 
    
    -- 查询“提交日期”列内不包含NULL 的学院(2) :使用CASE 表达式
    SELECT dpt
    FROM Students
    GROUP BY dpt
    HAVING COUNT(*) = SUM(CASE WHEN sbmt_date IS NOT NULL THEN 1 ELSE 0 END);
    
  • 相关阅读:
    python3 bytes数据类型探讨
    字典
    列表及元组
    在py文件中设置文件头
    函数的作用域、global与nonlocal
    python中 的意义及用法
    int、bool和str
    while循环、格式化输出、运算符和编码初识
    python初认识、基础数据类型以及 if 流程控制
    列表遍历和生成器遍历效率对比
  • 原文地址:https://www.cnblogs.com/sanzashu/p/11011227.html
Copyright © 2011-2022 走看看