SQL 苦手来请教各位大佬了。

2022-08-05 05:48:43 +08:00
 shadow1949

如何去统计 date 的前五天和前 10 天中,num 的平均值?需要跳过周末,往前顺延天数(有 SQL 可查询到所有周末日期)

id num date

1 5 2022-07-23

2 11 2022-07-21

3 22 2022-06-11

4 12 2022-06-10

3462 次点击
所在节点    程序员
34 条回复
dcsuibian
2022-08-05 05:53:16 +08:00
SQL 难做的话,考虑放程序里
shadow1949
2022-08-05 05:58:34 +08:00
@dcsuibian 好像必须 SQL 脚本,用来生成图表啥的 T T
lybcyd
2022-08-05 07:27:10 +08:00
利用 weekday 函数筛选出工作日
evi1j
2022-08-05 07:46:11 +08:00
select avg(num) from (select num ...... and not exists (周末表) order by 日期 desc ) limit 5 性能贼差🙄
documentzhangx66
2022-08-05 08:09:26 +08:00
在存储过程中,把问题分解为单步过程,利用临时表与变量,像写 java 一样,慢慢写不行嘛
hay313955795
2022-08-05 08:15:20 +08:00
前五天或者前十天的话 是不是可以这样.

select AVG(num) from table INNER JOIN
(select id from table where date_format(date,'%w')<6 and date >=DATE_SUB(NOW(),INTERVAL 30 DAY) ORDER BY date desc limit 5/10 )t1 on table.id = t1.id

date_format(date,'%w')<6 查询日期中非周末的数据
and date >=DATE_SUB(NOW(),INTERVAL 30 DAY) 根据 5 天或者 10 天的取值范围 确定一个稍微大范围的日期 比如 5 天那取的时间范围就是 10 天. 10 天里最多也就 4 天是周末.抛去 4 天还有 6 天也能满足.当然这个时间范围可以再进行调整.
我用的是 mysql
Qy2FbR
2022-08-05 08:16:25 +08:00
搞个 view 让 所有周末的值都是 0 , 取过去七天和十四天的平均值不就得了
cnhongwei
2022-08-05 08:23:06 +08:00
t1 一张虚拟表,有所有的日期, t2 一张虚拟表,有所有的日期,和是否是星期日, t1 和 t2 join ,条件是 t2 的日期 > t1 的日期并小于 t1 的日期 + 14 天(10 天内最多两个周末),这样得到 t3 ,对 t3 做窗口函数,计算 t1 和 t2 日期相差的天数, sum(不是周末)的记录数。再过滤相差天数为 10 的记录,这样得到 t4 开始日期 (来自 t1) 结束日期(来自 t2),这个天再和你现在的表进行 join ,并 sum(num)就可以了。
wxf666
2022-08-05 08:26:16 +08:00
『前五天』包括当天吗?比如,2022-07-23 『前五天』是( 23, 22, 21, 20, 19 )还是( 22, 21, 20, 19, 18 )?

『跳过周末,往前顺延』要将周末计算在内吗?比如,是(周一日六五四三二)还是(周一五四三二)?
shadow1949
2022-08-05 08:48:08 +08:00
@wxf666
前五天包括当前,是第一个;
周末不记在内,是第二个。
gongshuiwen
2022-08-05 08:51:04 +08:00
如果只是求日期前 5 天,可以查询日期前 7 天的记录,然后排除掉周末即可,原因在于任意连续的 7 天必定只包含一个周末,同理 10 天的话查询 14 天的数据,如果是非 5 的整数倍天数该方法不适用。

这是查询当前日期前 5 天的示例,注意不包括当天,查指定日期则把 NOW()替换掉即可:
```SQL
SELECT sum( num ) / 5 FROM test
WHERE date < NOW() and date >= date_sub(NOW(), INTERVAL 7 DAY ) AND weekday( date ) < 5;
```
cccmm
2022-08-05 08:52:17 +08:00
date 可重复? date 不一定连续?
提供一种思路
用这张带 num 的表 join 可以查询可以找到所有周末的 sql 得到只包含工作日的 num 和 date 的数据,让后按 date groupby 求出同一天的 num 平均值 再做出按日期倒序的 rowno 字段 row_number() over(order by date)
gongshuiwen
2022-08-05 08:53:21 +08:00
@shadow1949 包括当前日期的话改一下查询范围即可:

SELECT sum( num ) / 5 FROM test
WHERE date <= NOW() and date > date_sub(NOW(), INTERVAL 7 DAY ) AND weekday( date ) < 5;
cccmm
2022-08-05 08:53:55 +08:00
取前五天 10 天只需要 rowno 小雨=5 或者大雨等于 10 然后 avg
andrew2558
2022-08-05 08:54:16 +08:00
```mssql
SELECT AVG(num * 1.0) AS numavg
FROM (
SELECT TOP 5 *, 1 AS t
FROM test1
-- 过滤掉记录中所有星期六,星期天的 id
WHERE id NOT IN (
-- 获取所有星期六星期日的 id
SELECT id
FROM test1
WHERE DATEPART(weekday, date) IN (6, 7)
)
ORDER BY date
) tt
GROUP BY t
```
此代码在 sql 中可行
jucelin
2022-08-05 09:00:50 +08:00
必须 SQL 的话,可以用存储过程
复杂的 SQL 后期根本看不懂
reter
2022-08-05 09:07:45 +08:00
SQL 适合数据处理,清晰的业务处理,但不适合嵌入复杂的业务逻辑。比如考虑节假日,这明显就不适合纯 SQL 做。
vvtf
2022-08-05 09:10:52 +08:00
# 5 天, 因为去掉周末, 所以倒推 7 天, 10 天倒推 14 天
select
avg(num)
from table_name
where `date`>date_sub({someday},interval 7 day)
and `date`<={someday} and weekday(`date`)<5;

# 10 天
select
avg(num)
from table_name
where `date`>date_sub({someday},interval 14 day)
and `date`<={someday} and weekday(`date`)<5;
chendl111
2022-08-05 09:27:25 +08:00
用临时表筛选非周末的数据然后查询即可
wxf666
2022-08-05 09:39:14 +08:00
数据库新手试答一下

前面有大佬说了,任意连续 7 天必包含周六周日。只需算过去 7 天非周六周日的平均数即可

『 MySQL 语法(应该是这样吧)』:

WITH
  orig_data(date, num) AS (
   VALUES
    ROW('2022-07-29', 1), ROW('2022-07-23', 5),
    ROW('2022-07-30', 2), ROW('2022-07-21', 11),
    ROW('2022-07-31', 3), ROW('2022-06-11', 22),
    ROW('2022-08-01', 4), ROW('2022-06-10', 12),
    ROW('2022-08-02', 5),
    ROW('2022-08-03', 6),
    ROW('2022-08-04', 7),
    ROW('2022-08-05', 8)
 )

SELECT *,
    avg(CASE WHEN weekday(date) < 5 THEN num ELSE null END)
    OVER (ORDER BY date(date) RANGE INTERVAL 6 DAY PRECEDING) avg
  FROM orig_data


『结果』:

   date    num   avg
————— —— ————
2022-06-10   12   12.0000
2022-06-11   22   12.0000
2022-07-21   11   11.0000
2022-07-23   5   11.0000
2022-07-29   1   1.0000
2022-07-30   2   1.0000
2022-07-31   3   1.0000
2022-08-01   4   2.5000
2022-08-02   5   3.3333
2022-08-03   6   4.0000
2022-08-04   7   4.6000
2022-08-05   8   6.0000

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/870762

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX