程式碼片段(二):SQL片段
阿新 • • 發佈:2020-07-14
記錄一些破碎的,有意思的SQL片段
大都是日常工作中使用到的,但具體的業務場景也都記不清了,從有道雲筆記的記錄中扒拉出來,僅作記錄使用
MySQL部分
MySQL 5.7版本實現分組取topN
Hive,Oracle等資料庫系統都有row_number等函式,對於實現分組取topN之類的操作,都很簡單,MySQL8.x也實現了row_number,rank等諸多函式,但對於5.7版本來說,並沒有實現該功能,但又不會寫儲存過程,故鼓搗出下面的這個版本,僅供引數
-- 該功能實現的其實是 分組後,再分別去掉幾個最高值,去掉幾個最低值,然後再取平均數 select prov_id,avg(data_size_all) from ( select a.prov_id,a.data_size_all,a.daily_date,a.type,count(b.prov_id) from lf_zb_src_prov_d_quality_daily_anylize a left join lf_zb_src_prov_d_quality_daily_anylize b on a.prov_id = b.prov_id and a.type=1 and b.type=1 -- 關聯條件,不用管 and a.daily_date < b.daily_date -- 該條件是不等值連線,會導致關聯多次,下面用這個次數進行取topN where a.type=1 and b.type=1 -- 篩選條件,不用管 group by a.prov_id,a.data_size_all,a.daily_date,a.type -- 分組條件 having count(b.prov_id)<7 -- 取得是關聯次數小於7次的,再多加幾個,即可實現掐頭去尾取平均值 order by a.prov_id,a.daily_date ) c group by c.prov_id
實現累加需求
公司建模組的小姐姐來問了個問題:要計算一個使用者的一年內的話費累積額,也就是說他1月份花了100,二月份花了100,則出的結果是1月份100,2月份累計,是200,以此類推
-- 以下方案是百度後實現的,不記得是哪位大佬的方案了,只有但是把方案記錄在有道里,特此記錄一下 實現一: select t.* ,(select sum(price) from t_charge temp where temp.date <= t.date) as total_price from t_charge t group by t.id; 實現二: select t.*, sum(temp.price) as total_price from t_charge t,t_charge temp where t.date <= temp.date group by t.id;
group_concat的用法:分組後組內的全部concat起來
這一條隱約記得應該是計算所有延遲的省份數量,資料量變化在10%之上的省份列出來,其原始表結構以及忘記了,僅作為記錄group_concat使用的案例
SELECT daily_date AS "time", sum(case when delay_data_hour>=1 then 1 else 0 end) as delay_num, sum(case when remark is not null then 1 else 0 end) as repari_data_num, sum(case when datasize_charge >= 0.1 then 1 else 0 end ) as charge_num, GROUP_CONCAT(case when delay_data_hour>=1 then prov_name else null end,' ') as delay_prov_name, GROUP_CONCAT(case when remark is not null then prov_name else null end,' ') as repair_prov_name, GROUP_CONCAT(case when abs(datasize_charge)>=0.1 then prov_name else null end,' ') as charge_prov_name FROM lf_zb_src_prov_d_quality_daily_anylize WHERE now_date = DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 day),'%Y-%m-%d') and prov_name != '全國彙總' group BY time ---------------------------------------------------------------------------- time |delay_num |repari_data_num |charge_num |delay_prov_name |repair_prov_name |charge_prov_name | -----------|----------|----------------|-----------|--------------------|--------------------------|--------------------| 2019-02-25 |5 |5 |4 |河南 ,廣西 ,海南 ,福建 ,安徽 |黑龍江 ,遼寧 ,吉林 ,,福建 ,浙江 ,江蘇 ,上 | 資料做了部分修改
一個不同的合併方式
昨晚加班到很晚,建模組的小姐姐又來難為我了
小姐姐:要實現下面的結果。
我: 為啥要有這麼與眾不同的需求
小姐姐:你就說能不能幹吧?
我:這還不簡單嘛!
select id,max(c_1) ,max(c_2) from(
select ta.id,ta.c_1 as c_1 ,null as c_2 from table_a ta
union
select tb.id ,null as c_1,tb .c_2 from table_b tb
)a
group by id
其內層結構如下
應該還有其他方法,暫時還未想到,記錄一下
MySQL使用select出來的值進行更新
該需求的場景是,我們要把Hive元資料裡的表,全部同步一份到我們公司的專案平臺上,專案平臺的表分為table_info表,column_info表,partition_info表,現在各表都已經同步完畢。但是1.0版本的檢索使用的是table_info中的full_search欄位(2.0版本是使用elasticsearch解決),所以現在需要先更新該欄位。
-- 使用了group_concat和使用select出來的值,進行join關聯後更新,表結構記不得了,只有筆記了,記錄下思路,以備他日之需
SET SESSION group_concat_max_len = 102400; -- 修復concat_ws過長被截斷
UPDATE unicom_advanced.ubd_table_info t4 INNER JOIN
(
select
table_id,concat(replace(a,char(13),''),replace(b,char(13),'')) as full_search
from (
select
t1.table_id,
concat(t1.table_code,'|',t1.table_name,'|',t1.desc_info,'|',t1.table_business_desc,'|') a,
group_concat(t2.column_name,t2.column_code,'|',t5.partition_code,'|',t5.partition_name) as b
from unicom_advanced.ubd_table_info t1
left join unicom_advanced.ubd_column_info t2
on t1.table_id = t2.table_id
left join unicom_advanced.ubd_partition_info t5
on t1.table_id = t5.table_id
-- where t1.table_id in (1363372844563160069,1363372844563160581,1363372844563160837,1363372844563161605,1363372844563160070,1363372844563160582)
group by t1.table_id
)c
group by table_id
) as t3
ON t4.table_id=t3.table_id
set t4.full_search=t3.full_search;