技术分享
🗒️[实践]一道SQL题引发的思考
00 分钟
2023-12-29
2023-12-29
type
status
date
slug
summary
tags
category
icon
password

题目

下面的t1表中的数据为用户A的访问记录,请计算每个月的访问的天数。返回 year,month,days 格式。
正确结果返回应该为:

答案一

答案二

分析

我的答案

一开始,我想着,先对年月日进行一次去重,因为只需要计算一个月的天数,所以重复的数据是没有用的。
然后,在上面的结果的基础上,根据年月进行分组计算日的数量。

标准答案

然而,看了一眼标准答案,惊为天人,用了两个位运算的函数 BIT_COUNTBIT_OR ,还有左移符号 <<
看第一眼,没看懂了,看第二眼,还是没有看懂。
  • BIT_COUNT 计算对应的数的二进制中的1的数量,例如
  • BIT_OR 可以理解为按位或,就是对 select出来的字段的值的列表,进行所有按位或操作。
继续分析:
  1. 1<<day:这是一个位左移操作。它将数字1向左移动day位。在这里,day很可能是一个代表月份中某一天的字段。例如,如果day是2,那么1<<day的结果是4(二进制中的100),这相当于2的day次方。
  1. BIT_OR(1<<day)BIT_OR是一个聚合函数,它对组内所有行执行位或(bitwise OR)操作。在这个查询中,它将同一个yearmonth组内的所有1<<day的结果进行位或操作。这样,每个不同的day都会在结果中设置一个位。因为每个月的天数是唯一的,所以这个操作最终会产生一个整数,其二进制表示中的位数表示该月中出现的不同天数。【不超过32天,位数不会超过31,可以使用BIT_OR
  1. BIT_COUNT(BIT_OR(1<<day))BIT_COUNT函数计算一个数字的二进制表示中1的数量。在这个查询中,它计算上一步BIT_OR操作结果中的位数,这个位数就是该月中有记录的不同天数。
  1. GROUP BY year,month:这个语句指示MySQL按照年和月来分组记录。对于每个组,上述的位运算将单独执行。
综上所述,这个查询对于每个月份,计算了t1表中有记录的不同天数。这种方法特别适用于处理稀疏数据,即不是每一天都有记录的情况。通过位运算,它能高效地对存在记录的天数进行计数,而不需要存储一个完整的日期列表。

总结

位运算的函数还是挺有效的,学习了。
 
 
上一篇
Day98【概念解析】Bin Log
下一篇
Day97【概念解析】SWOT Analysis

评论
Loading...