0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

通過(guò)SQL計(jì)算同時(shí)在線問(wèn)題

數(shù)據(jù)分析與開(kāi)發(fā) ? 來(lái)源:CSDN博客 ? 作者:石榴公子YYDS ? 2021-09-30 14:22 ? 次閱讀

本文是通過(guò) SQL 計(jì)算同時(shí)在線問(wèn)題,即求最高在線人數(shù)以及最高峰時(shí)間段。

0 需求分析

數(shù)據(jù)為主播ID,stt表示開(kāi)播時(shí)間,edt表示下播時(shí)間。

idsttedt

10012021-06-14 12122021-06-14 1812

10032021-06-14 13122021-06-14 1612

10042021-06-14 13122021-06-14 2012

10022021-06-14 15122021-06-14 1612

10052021-06-14 15122021-06-14 2012

10012021-06-14 20122021-06-14 2312

10062021-06-14 21122021-06-14 2312

10072021-06-14 22122021-06-14 2312

求:

(1)該平臺(tái)某一天主播同時(shí)在線人數(shù)最高為多少?

(2)出現(xiàn)最高峰的時(shí)間段是哪個(gè)時(shí)間?

1 數(shù)據(jù)準(zhǔn)備

(1)數(shù)據(jù)

vim play.txt

idstt edt

10012021-06-14 1212 2021-06-14 1812

10032021-06-14 13122021-06-14 1612

10042021-06-14 13122021-06-14 2012

10022021-06-14 15122021-06-14 1612

10052021-06-14 15122021-06-14 2012

10012021-06-14 20122021-06-14 2312

10062021-06-14 21122021-06-14 2312

10072021-06-14 22122021-06-14 2312

(2) 建表

create table if not exists play(

id string,

stt string,

edt string

row format delimitedfields terminated by ‘ ’

;

(3 )加載數(shù)據(jù)

load data local inpath “/home/centos/dan_test/play.txt” into table play;

(4) 查詢數(shù)據(jù)

hive》 select * from play;

OK

1001 2021-06-14 12:12:12 2021-06-14 18:12:121003 2021-06-14 13:12:12 2021-06-14 16:12:121004 2021-06-14 13:15:12 2021-06-14 20:12:121002 2021-06-14 15:12:12 2021-06-14 16:12:121005 2021-06-14 15:18:12 2021-06-14 20:12:121001 2021-06-14 20:12:12 2021-06-14 23:12:121006 2021-06-14 21:12:12 2021-06-14 23:15:121007 2021-06-14 22:12:12 2021-06-14 23:10:12

Time taken: 0.087 seconds, Fetched: 8 row(s)

2 數(shù)據(jù)分析

問(wèn)題1分析:

本題如果直接從SQL本身很難下手,無(wú)從做起,不妨我們換個(gè)思路,假定我們拿到的是一條數(shù)據(jù),現(xiàn)在用java程序怎么做?其實(shí)就是一個(gè)累加器的思想(如SPARK的累加器)。首先我們需要將這樣一條記錄進(jìn)行拆分,分成不同的記錄或數(shù)據(jù)流進(jìn)入累加器,然后給每條記錄進(jìn)行標(biāo)記,如果開(kāi)播的話該條記錄記為1,下播的話記為-1,此時(shí)的數(shù)據(jù)流按照時(shí)間順序依次進(jìn)入累加器,然后在累加器中進(jìn)行疊加,其中累計(jì)的結(jié)果最大時(shí)候就是所求的結(jié)果。其實(shí)本質(zhì)是利用累加器思想,但進(jìn)入累加器的數(shù)據(jù)是按時(shí)間排好序的時(shí)序流數(shù)據(jù)(數(shù)據(jù)進(jìn)入按時(shí)間先后順序進(jìn)入)。

上述思路總結(jié)如下:

(1)將數(shù)據(jù)切分(按起始時(shí)間和結(jié)束時(shí)間)

(2)數(shù)據(jù)進(jìn)行標(biāo)簽,開(kāi)播的記錄為記為1,下播的記錄記為-1用于累加

(2)將數(shù)據(jù)按時(shí)間進(jìn)行排序

(3)數(shù)據(jù)進(jìn)入累加器進(jìn)行累加

(4)獲取累加器中當(dāng)前累加值最大的數(shù)值

有了以上思路后,我們將其轉(zhuǎn)換為SQL求解思路。

(1)將數(shù)據(jù)切分:實(shí)際上就是將開(kāi)播時(shí)間和下播時(shí)間轉(zhuǎn)換成一條條記錄。也就是列轉(zhuǎn)行,我們用熟悉的UNION操作,進(jìn)行轉(zhuǎn)換。

select id,stt dt from play

unionselect id,edt dt from play

--------------------------------------------------------------------------------

OK

1001 2021-06-14 12:12:121001 2021-06-14 18:12:121001 2021-06-14 20:12:121001 2021-06-14 23:12:121002 2021-06-14 15:12:121002 2021-06-14 16:12:121003 2021-06-14 13:12:121003 2021-06-14 16:12:121004 2021-06-14 13:15:121004 2021-06-14 20:12:121005 2021-06-14 15:18:121005 2021-06-14 20:12:121006 2021-06-14 21:12:121006 2021-06-14 23:15:121007 2021-06-14 22:12:121007 2021-06-14 23:10:12

Time taken: 20.502 seconds, Fetched: 16 row(s)

(2) 數(shù)據(jù)標(biāo)記。在上述SQL基礎(chǔ)上直接進(jìn)行標(biāo)記即可。如果數(shù)據(jù)本來(lái)就是分開(kāi)的則用case when進(jìn)行標(biāo)記。

select id,stt dt , 1 flag from play

unionselect id,edt dt ,-1 flag from play

--------------------------------------------------------------------------------

OK

1001 2021-06-14 12:12:12 11001 2021-06-14 18:12:12 -11001 2021-06-14 20:12:12 11001 2021-06-14 23:12:12 -11002 2021-06-14 15:12:12 11002 2021-06-14 16:12:12 -11003 2021-06-14 13:12:12 11003 2021-06-14 16:12:12 -11004 2021-06-14 13:15:12 11004 2021-06-14 20:12:12 -11005 2021-06-14 15:18:12 11005 2021-06-14 20:12:12 -11006 2021-06-14 21:12:12 11006 2021-06-14 23:15:12 -11007 2021-06-14 22:12:12 11007 2021-06-14 23:10:12 -1

Time taken: 7.408 seconds, Fetched: 16 row(s)

(3)數(shù)據(jù)按照時(shí)間排序,進(jìn)入累加器進(jìn)行累加(按時(shí)間排序是累加的關(guān)鍵)

select id

,dt

,sum(flag) over(order by dt) as cur_cnt

from(

select id,stt dt , 1 flag from play

union

select id,edt dt ,-1 flag from play

) t

--------------------------------------------------------------------------------

OK

1001 2021-06-14 12:12:12 11003 2021-06-14 13:12:12 21004 2021-06-14 13:15:12 31002 2021-06-14 15:12:12 41005 2021-06-14 15:18:12 51002 2021-06-14 16:12:12 31003 2021-06-14 16:12:12 31001 2021-06-14 18:12:12 21001 2021-06-14 20:12:12 11004 2021-06-14 20:12:12 11005 2021-06-14 20:12:12 11006 2021-06-14 21:12:12 21007 2021-06-14 22:12:12 31007 2021-06-14 23:10:12 21001 2021-06-14 23:12:12 11006 2021-06-14 23:15:12 0

Time taken: 8.133 seconds, Fetched: 16 row(s)

(4) 獲取累加器中當(dāng)前時(shí)刻累加的最大值,即為同時(shí)開(kāi)播最多的人數(shù)

select max(cur_cnt)

from(

select id

,dt

,sum(flag) over(order by dt) as cur_cnt

from(

select id,stt dt , 1 flag from play

union

select id,edt dt ,-1 flag from play

) t

) m

--------------------------------------------------------------------------------

OK

5

Time taken: 13.087 seconds, Fetched: 1 row(s)

問(wèn)題2分析:

第二問(wèn)求的是出現(xiàn)高峰時(shí)的時(shí)間段,也就是高峰時(shí)間的起始時(shí)間及結(jié)束時(shí)間,或持續(xù)時(shí)長(zhǎng)。

借鑒第一問(wèn)的結(jié)果進(jìn)行分析:

select *,max(cur_cnt) over()

from(

select id

,dt

,sum(flag) over(order by dt) as cur_cnt

from(

select id,stt dt , 1 flag from play

union

select id,edt dt ,-1 flag from play

) t

) m

通過(guò)上圖我們可以看出當(dāng)由峰值出的記錄時(shí)間到下一條記錄人數(shù)減少的時(shí)候這一段時(shí)間即為峰值持續(xù)的時(shí)間,或高峰的時(shí)間段,也就是求出峰值的下一條記錄的時(shí)間與峰值對(duì)應(yīng)記錄的時(shí)間即為高峰時(shí)間段,因此利用lead()函數(shù)很容易求出問(wèn)題的答案。SQL如下:

select max_cur_cnt

,dt as start_time

,lead_dt as end_time

from(

select *

,lead(dt,1,dt) over(order by dt) lead_dt

from(

select *,max(cur_cnt) over() as max_cur_cnt

from(

select id

,dt

,flag

,sum(flag) over(order by dt) as cur_cnt

from(

select id,stt dt , 1 flag from play

union

select id,edt dt ,-1 flag from play

) t

) m

) n

) p

where cur_cnt=max_cur_cnt

計(jì)算結(jié)果如下:

--------------------------------------------------------------------------------

OK

5 2021-06-14 15:18:12 2021-06-14 16:12:12

Time taken: 17.513 seconds, Fetched: 1 row(s)

3 小結(jié)

本文針對(duì)SQL統(tǒng)計(jì)同時(shí)在線人數(shù)問(wèn)題進(jìn)行了分析,利用累加器思想對(duì)該問(wèn)題進(jìn)行求解,最終劃歸為時(shí)序數(shù)據(jù),進(jìn)行時(shí)序數(shù)據(jù)分析(常用技巧:打標(biāo)簽,形成序列,多序列進(jìn)行分析),最后利用sum() over()對(duì)標(biāo)簽進(jìn)行累加求出當(dāng)前在線人數(shù)本題最關(guān)鍵的點(diǎn)在于轉(zhuǎn)換為時(shí)序數(shù)據(jù)及累加器的思想,望讀者能夠掌握。

事實(shí)上該問(wèn)題的分析在業(yè)務(wù)上具有重要的意義,我們能夠?qū)崟r(shí)跟蹤隨著時(shí)間變化的在線人數(shù),了解服務(wù)器的負(fù)載變化情況,服務(wù)器的實(shí)時(shí)并發(fā)數(shù)等。該問(wèn)題在不同業(yè)務(wù)場(chǎng)景下,有不同意義,比如某個(gè)游戲的同時(shí)在線人數(shù),比如某個(gè)服務(wù)器的實(shí)時(shí)并發(fā)數(shù),比如某個(gè)倉(cāng)庫(kù)的貨物積壓數(shù)量,某一段時(shí)間內(nèi)的同時(shí)處于服務(wù)過(guò)程中的最大訂單量等。實(shí)際上求最大在線人數(shù)和求實(shí)時(shí)在線人數(shù)是一回事,最大人數(shù)依賴于當(dāng)前在線人數(shù)表,只有先求出當(dāng)前在線人數(shù)表,才能求出最大同時(shí)在線人數(shù)。

不謀全局者,不足以謀一域。

不謀萬(wàn)世者,不足以謀一時(shí)。

作者: 石榴公子YYDS

https://blog.csdn.net/godlovedaniel/article/details/118651811

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    6837

    瀏覽量

    88754
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    753

    瀏覽量

    44036

原文標(biāo)題:3 小結(jié)

文章出處:【微信號(hào):DBDevs,微信公眾號(hào):數(shù)據(jù)分析與開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    什么是 Flink SQL 解決不了的問(wèn)題?

    簡(jiǎn)介 在實(shí)時(shí)數(shù)據(jù)開(kāi)發(fā)過(guò)程中,大家經(jīng)常會(huì)用 Flink SQL 或者 Flink DataStream API 來(lái)做數(shù)據(jù)加工。通常情況下選用2者都能加工出想要的數(shù)據(jù),但是總會(huì)有 Flink SQL
    的頭像 發(fā)表于 07-09 20:50 ?246次閱讀

    SQL全外連接剖析

    SQL中的全外連接是什么? 在SQL中,F(xiàn)ULLOUTERJOIN組合左外連接和右外連接的結(jié)果,并返回連接子句兩側(cè)表中的所有(匹配或不匹配)行。接下面sojson給大家詳細(xì)講解。 ? 圖解:SQL
    的頭像 發(fā)表于 03-19 18:28 ?2090次閱讀
    <b class='flag-5'>SQL</b>全外連接剖析

    為什么需要監(jiān)控SQL服務(wù)器?

    服務(wù)器是存儲(chǔ)、處理和管理數(shù)據(jù)的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng) (RDBMS) 工具或軟件,例如Microsoft的MSSQL、Oracle DB和PostgreSQL。此外,服務(wù)器執(zhí)行SQL查詢和命令來(lái)操作關(guān)系數(shù)據(jù)庫(kù)。實(shí)際上,SQL服務(wù)器將托管數(shù)據(jù)庫(kù)和
    的頭像 發(fā)表于 02-19 17:19 ?430次閱讀

    如何用Rust過(guò)程宏魔法簡(jiǎn)化SQL函數(shù)呢?

    這是 RisingWave 中一個(gè) SQL 函數(shù)的實(shí)現(xiàn)。只需短短幾行代碼,通過(guò)在 Rust 函數(shù)上加一行過(guò)程宏,我們就把它包裝成了一個(gè) SQL 函數(shù)。
    的頭像 發(fā)表于 01-23 09:43 ?860次閱讀
    如何用Rust過(guò)程宏魔法簡(jiǎn)化<b class='flag-5'>SQL</b>函數(shù)呢?

    分布式無(wú)紙化交互系統(tǒng)如何支持多用戶同時(shí)在線編輯和協(xié)作?

    分布式無(wú)紙化交互系統(tǒng)通過(guò)以下方式支持多用戶同時(shí)在線編輯和協(xié)作: 實(shí)時(shí)同步技術(shù) :系統(tǒng)使用實(shí)時(shí)同步技術(shù),確保多個(gè)用戶在同時(shí)編輯同一份文檔時(shí),每個(gè)人都能看到其他人的操作,并能夠?qū)崟r(shí)互動(dòng)和協(xié)作。 版本控制
    的頭像 發(fā)表于 01-15 15:33 ?376次閱讀

    數(shù)據(jù)庫(kù)編程大賽:一條SQL計(jì)算撲克牌24點(diǎn)

    參加NineData舉辦的數(shù)據(jù)庫(kù)編程大賽,展示你的技術(shù)才華!用一條SQL語(yǔ)句解決撲克牌24點(diǎn)的計(jì)算表達(dá)式。這場(chǎng)比賽面向數(shù)據(jù)庫(kù)愛(ài)好者、開(kāi)發(fā)者、程序員、DBA等,展示你的編程技能,并有機(jī)會(huì)贏得豐厚獎(jiǎng)勵(lì)。歡迎大家來(lái)挑戰(zhàn)!
    的頭像 發(fā)表于 12-21 15:24 ?698次閱讀
    數(shù)據(jù)庫(kù)編程大賽:一條<b class='flag-5'>SQL</b><b class='flag-5'>計(jì)算</b>撲克牌24點(diǎn)

    SQL核心知識(shí)點(diǎn)總結(jié)

    SQL:Structure Query Language。(結(jié)構(gòu)化查詢語(yǔ)言),通過(guò)sql操作數(shù)據(jù)庫(kù)(操作數(shù)據(jù)庫(kù),操作表,操作數(shù)據(jù))
    的頭像 發(fā)表于 12-13 10:28 ?1343次閱讀
    <b class='flag-5'>SQL</b>核心知識(shí)點(diǎn)總結(jié)

    Oracle如何執(zhí)行sql腳本文件

    Oracle是一種關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),可用于存儲(chǔ)、查詢和管理大量的數(shù)據(jù)。在Oracle中,可以通過(guò)執(zhí)行SQL腳本文件來(lái)一次性地執(zhí)行多個(gè)SQL語(yǔ)句或者批量處理數(shù)據(jù)。在下面的文章中,我將詳細(xì)介紹
    的頭像 發(fā)表于 12-06 10:51 ?6298次閱讀

    oracle執(zhí)行sql查詢語(yǔ)句的步驟是什么

    Oracle數(shù)據(jù)庫(kù)是一種常用的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),具有強(qiáng)大的SQL查詢功能。Oracle執(zhí)行SQL查詢語(yǔ)句的步驟包括編寫SQL語(yǔ)句、解析SQL語(yǔ)句、生成執(zhí)行計(jì)劃、執(zhí)行
    的頭像 發(fā)表于 12-06 10:49 ?880次閱讀

    oracle sql 定義變量并賦值

    在Oracle SQL中,變量是用來(lái)存儲(chǔ)數(shù)據(jù)值的標(biāo)識(shí)符。通過(guò)定義和使用變量,我們可以在SQL語(yǔ)句中使用它們來(lái)存儲(chǔ)和處理數(shù)據(jù),從而實(shí)現(xiàn)更靈活和動(dòng)態(tài)的查詢和操作。 在Oracle SQL
    的頭像 發(fā)表于 12-06 10:46 ?2588次閱讀

    oracle用的是sql語(yǔ)句嗎

    是的,Oracle使用的是SQL語(yǔ)言。SQL(Structured Query Language)是一種用于管理和操作關(guān)系型數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)編程語(yǔ)言,被廣泛應(yīng)用于企業(yè)級(jí)數(shù)據(jù)庫(kù)系統(tǒng)中,包括Oracle
    的頭像 發(fā)表于 12-06 10:30 ?989次閱讀

    sql語(yǔ)句多個(gè)條件怎么連接

    SQL中,多個(gè)條件可以使用邏輯運(yùn)算符連接,常用的邏輯運(yùn)算符有AND、OR和NOT。這些運(yùn)算符可以幫助我們?cè)诓樵冎兄付ǘ鄠€(gè)條件以過(guò)濾數(shù)據(jù),從而獲得我們需要的結(jié)果集。 AND運(yùn)算符用于同時(shí)滿足多個(gè)條件
    的頭像 發(fā)表于 11-23 11:34 ?2269次閱讀

    sql where條件的執(zhí)行順序

    SQL語(yǔ)句中的WHERE條件是用來(lái)篩選數(shù)據(jù)的,它決定了哪些數(shù)據(jù)會(huì)被返回給用戶。WHERE條件的執(zhí)行順序是影響SQL語(yǔ)句性能的一個(gè)重要因素,正確地理解和優(yōu)化WHERE條件的執(zhí)行順序可以提高查詢效率
    的頭像 發(fā)表于 11-23 11:31 ?2123次閱讀

    mysql和sql server區(qū)別

    MySQL和SQL Server是兩種常見(jiàn)的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS),用于存儲(chǔ)和管理數(shù)據(jù)庫(kù)。雖然它們都支持SQL語(yǔ)言,但在其他方面存在一些顯著的區(qū)別。以下是MySQL和SQL Server
    的頭像 發(fā)表于 11-21 11:07 ?1454次閱讀

    sql中日期函數(shù)的用法

    查詢中進(jìn)行日期計(jì)算和比較。 一、創(chuàng)建日期和時(shí)間數(shù)據(jù) 在SQL中,我們可以使用以下函數(shù)創(chuàng)建日期和時(shí)間數(shù)據(jù): CURRENT_DATE:返回當(dāng)前日期。 CURRENT_TIME:返回當(dāng)前時(shí)間。 CURRENT_TIMESTAMP:返回當(dāng)前日期和時(shí)間。 這些函數(shù)可以用于在插入或
    的頭像 發(fā)表于 11-17 16:24 ?964次閱讀