sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现

这篇具有很好参考价值的文章主要介绍了sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 二级分组需求

  • 先按照一个字段分组,在按照 第二个字段分组。
  • 之后,如果 这个 二级分组中的数据,是 > 1条的。就筛选出来。

比如:

  • 先按照 站点分组,再按照 设备分组,

  • 即:如果站点上配置了2个设备。就筛选出来。

    • 然后:这2个设备 都必须是屏幕
  • 查出配置了2个设备的站点

SELECT
	e2.station,
	e2.device 
FROM
	esb_config e2 
GROUP BY
	e2.station 
HAVING
	count( 1 ) > 1
  • 要求 这两个设备都是屏幕,参考SQL和思路1

错误写法

	SELECT
		e2.station,
		e2.device 
	FROM
		esb_config e2
		GROUP BY e2.station,e2.device HAVING count(*) > 1 
	
-- 这样是错误的,这样是根据2个字段 分组。结果不会存在 > 1的情况
GROUP BY e2.station HAVING count(e2.device) > 1
-- 这样写无异议 等于 HAVING count(e2.station) > 1,也是错误的

GROUP BY e2.station
-- 核心是:这样查询后,会随机带出 一个device。
-- 所以哪怕 外层在套一个分组(因为经过一层后,已经选出了一个device了),也是错的。

问题从头整理

表结构和数据

CREATE TABLE `user` (
  `id` int NOT NULL,
  `username` varchar(22) DEFAULT NULL,
  `info` varchar(22) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


1	zhangsan	1
2	lisi	22
3	lisi	33

-- 我们要查出lisi
-- 先按照姓名分组,在按照 info 分组。
-- info中的 数据>1,就查询出来
collate/kəˈleɪt/
vt.
核对,校对;校勘

按照username分组

SELECT * 
FROM `user`
GROUP BY username

-- 按照username分组后,lisi会随机选一条(第一条)
1	zhangsan	1
2	lisi	22

加入扰乱数据

INSERT INTO `user`(`id`, `username`, `info`) VALUES (4, 'zhangsan', '1');
-- 此时数据的数据为
1	zhangsan	1
2	lisi	22
3	lisi	33
4	zhangsan	1
  • 加条件
SELECT * 
FROM `user`
GROUP BY username
HAVING count(username) > 1

-- 结果为:此时zhangsan是info相同的,不应该出现。count(1),或 count(其他值) 结果都一样
1	zhangsan	1
2	lisi	22

两个字段分组 加条件

  • 分3组
-- 此时数据的数据为
1	zhangsan	1
2	lisi	22
3	lisi	33
4	zhangsan	1

SELECT * 
FROM `user`
GROUP BY username,info

-- 根据 两个字段分组,后变成3组
1	zhangsan	1
2	lisi	22
3	lisi	33
  • 此时分组中的数据 > 1的为 zhangsan
SELECT * 
FROM `user`
GROUP BY username,info
HAVING count(1) > 1

-- 结果
1	zhangsan	1

2. 业务

真实的问题

  • 业务要求了,必须是 一个站点绑定两个设备都是屏幕,才查询出来。

  • 无用的SQL保存,验证这个真实的设备是不是 屏幕

SELECT
	* 
FROM
	device d,
	device_type dt 
WHERE
	d.deviceType = dt.id 
	AND d.id = 'e696cfeeb4568ccfcda0ae6787388760' 
	AND dt.attribute = '屏幕'

先 where,在 having

  • where语句的执行顺序先于group by,group by语句的执行顺序先于having
    • having 子句中的每一个元素也必须出现在select列表中,
    • having语句可以使用聚合函数。

SQL和实现思路1 窗口函数

SELECT
	* 
FROM
	(
	SELECT
		e2.station,
		ROW_NUMBER() OVER ( PARTITION BY e2.station ) row_num 
	FROM
		esb_config e2,
		device d,
		device_type dt 
	WHERE
		d.deviceType = dt.id 
		AND dt.attribute = '屏幕' 
		AND e2.device = d.id 
	) t1 
WHERE
	t1.row_num > 1
	
-- 窗口函数 再次赋值
SELECT
	* 
FROM
	(
	SELECT
		e2.station,
		ROW_NUMBER() OVER ( PARTITION BY e2.station ) row_num 
	FROM
		esb_config e2
	) t1
WHERE
	t1.row_num > 1

SQL和实现思路2 分组

  • 查出 站点配置了 多个设备的 站点
SELECT
	e2.station,
	e2.device 
FROM
	esb_config e2 
GROUP BY
	e2.station 
HAVING
	count( 1 ) > 1
  • 这多个设备 必须是屏幕,才能查出来。
    • 对站点进行了分组:
SELECT
	e2.station,
	e2.device 
FROM
	esb_config e2,
	device d,
	device_type dt 
WHERE
	d.deviceType = dt.id 
	AND dt.attribute = '屏幕' 
	AND e2.device = d.id
-- 上面SQL 查出了配置表中,所有为屏幕的 设备和站点
-- 此时一个站点 如果配置了 多个屏幕,这个站点就会展示出多条

-- 然后在筛选一下,站点>1 的
GROUP BY
	e2.station 
HAVING
	count( 1 ) > 1

扩展怎么显示 一个站点,显示2次呢

  • 思路1再关联原表

  • 使用这个逻辑,有一个问题。怎么显示 一个站点,显示2次呢(设备不同的时候)

    • 很简单,只需要在 外层关联一个 表即可(因为这个表 本来就是这种逻辑,一个站点,显示2次)
SELECT * from esb_config e1, (

	SELECT
		e2.station 
	FROM
		esb_config e2,
		device d,
		device_type dt 
	WHERE
		d.deviceType = dt.id 
		AND dt.attribute = '屏幕' 
		AND e2.device = d.id 
	GROUP BY
		e2.station 
	HAVING
		count( 1 ) > 1
) t1
WHERE e1.station = t1.station



-- 核心是这样的结果
SELECT * from esb_config e1, (

	SELECT
		e2.station -- 这里,e2.device 取了没用,只是会筛选第一个 
	FROM
		esb_config e2
	GROUP BY
		e2.station 
	HAVING
		count( e2.station  ) > 1

) t1
WHERE e1.station = t1.station

-- 那这个结果加上限制对不对呢?不对的,为啥不对,这里不懂。
-- AND dt.attribute = '屏幕' 

SQL和思路3 错误的

  • 把一级分组,查询出来

  • 把二级分组,查询出来

  • 如果 一级分组 和 二级分组,关联上就展示

  • 这样 查出的数据 只查出了一条(也是上面的 数据之一)文章来源地址https://www.toymoban.com/news/detail-636636.html

SELECT
	* 
FROM
	( 
		SELECT * FROM (
			SELECT
				e2.station,
				e2.device
			FROM
				esb_config e2,
				device d,
				device_type dt 
			WHERE
				e2.device = d.id 
				AND d.deviceType = dt.id 
				AND dt.attribute = '屏幕'
		) t2
		GROUP BY t2.station HAVING count(t2.station) > 1 
	) t1,
	
(SELECT * FROM (
	SELECT
		e2.station,
		e2.device 
	FROM
		esb_config e2,
		device d,
		device_type dt 
	WHERE
		e2.device = d.id 
		AND d.deviceType = dt.id 
		AND dt.attribute = '屏幕'
		) t2
		GROUP BY t2.device HAVING count(t2.device) > 1 
	) t3
	
WHERE
	t1.station = t3.station and t1.device = t3.device

到了这里,关于sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spark_SQL函数定义(定义UDF函数、使用窗口函数)

                        一、UDF函数定义         (1)函数定义         (2)Spark支持定义函数         (3)定义UDF函数                 (4)定义返回Array类型的UDF         (5)定义返回字典类型的UDF 二、窗口函数         (1)开窗函数简述         (2)

    2024年02月03日
    浏览(48)
  • HIVE SQL 根据主键去重并实现其余字段分组聚合

    相同个人id下所有字段按时间顺序补位,取首个不为空值 * 注意:此处是取的首个不为空(即不为null)的字段,所以在实际使用过程中应提前将空字符串转为null值。

    2024年02月16日
    浏览(47)
  • 玩转SQL语句之group by 多字段分组查询与having子句,一篇解决你的疑惑!

    分组,顾名思义,分成小组。简而言之就是就是把相同的数据分到一个组。 如下表(表名gb),里面有16条数据,前8条是狗狗,后8条是猫猫. 现在对name这个列进行分组查询 得到结果如下: 我们发现他把原始表分为了两个小组,狗狗小组和猫猫小组。从这可以看出分组查询就

    2023年04月18日
    浏览(45)
  • SQL函数 - 开窗(窗口)函数

    开窗函数对一组值进行操作,它不像普通聚合函数那样需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列 开窗函数的语法形式为:函数 + over(partition by 分组用列 order by 排序用列),表示对数据集按照分组用列进行分区,并且并且对每个分区按

    2024年02月14日
    浏览(54)
  • 【大数据Hive3.x数仓开发】窗口函数案例:连续N次登录的用户;级联累加求和;分组TopN

    对窗口函数的讲解part见:【大数据Hive3.x数仓开发】函数–窗口函数 自连接过滤实现 连续两天登陆的用户ID: 窗口函数lead()实现 功能:用于从当前数据中基于当前行的数据向后偏移取值 语法: lead(colName,N,defautValue) colName:取哪一列的值 N:向后偏移N行 defaultValue:如果取不到返回

    2023年04月17日
    浏览(35)
  • SQL—排序专用窗口函数

    下面介绍三种用于进行排序的专用窗口函数: 1、RANK()     在计算排序时,若存在相同位次,会跳过之后的位次。     例如,有3条排在第1位时,排序为:1,1,1,4······ 2、DENSE_RANK()     这就是题目中所用到的函数,在计算排序时,若存在相同位次,不会跳过之后的位

    2024年01月22日
    浏览(48)
  • SQL - 开窗(窗口)函数

    开窗函数对一组值进行操作,它不像普通聚合函数那样需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列 开窗函数的语法形式为:函数 + over(partition by 分组用列 order by 排序用列),表示对数据集按照分组用列进行分区,并且并且对每个分区按

    2024年02月12日
    浏览(44)
  • SQL-窗口函数

    什么是窗口函数 可以像聚合函数一样对一组数据进行分析并返回结果,二者的不同之处在于,窗口函数不是将一组数据汇总成单个结果,而是为每一行数据都返回一个结果。 窗口函数组成部分 1.创建数据分区 窗口函数OVER子句中的PARTITION BY选项用于定义分区,其作用类似于查

    2024年01月19日
    浏览(40)
  • 【SQL】MySQL中的窗口函数(开窗函数)

    窗口函数是 MYSQL8.0 新增的 聚合函数: 多行变一行,常见的sum,count,max,min 窗口函数: 行数不变,常见的row_number,rank 语法格式: 窗口函数(表达式) over (partition by … order by … frame_clause) partition by是分区,类似于group by,如去掉相当于对所有数据进行计算 order by排序 frame_c

    2024年02月07日
    浏览(51)
  • 在 SQL Server 中,可以使用加号运算符(+)来拼接字符串。但是,如果需要拼接多个字符串或表中的字段,就需要使用内置的拼接函数了

    以下是 SQL Server 中的一些内置拼接函数: 1. CONCAT:将两个或多个字符串拼接在一起。语法为: 示例: 2. CONCAT_WS:与 CONCAT 类似,但可以指定一个分隔符。语法为: 示例: 3. CONCATN:将多个字符串拼接在一起,并在每个字符串之间添加指定的字符。语法为: 示例: 4. REPLAC

    2024年02月07日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包