sql基礎操作


數據分析面試必備——SQL你准備好了嗎?

2019-05-31 17:03

img

數據分析師的招聘JD你們一定不陌生:

img

可以說,不是每個數據分析崗都要求python,但是每個數據分析崗都需要會SQL。寫這篇文章是希望幫助還沒有實戰過SQL的小伙伴、或者了解一些SQL語句,但是擔心自己了解的太片面的小伙伴。

這篇文章主要介紹的是:如果想要面試數據分析崗位,最優先需要掌握的SQL技能是哪些呢?讀完本文,你能快速知道:

1、除了select 這種基本的語句,我最應該馬上掌握的SQL語句和知識是什么?

2、面試中SQL題80%都在考察的語法是什么?

3、這些語法應該怎么使用?

本文將從三大塊介紹入門SQL需要掌握的語法和知識,分別是最基礎的選擇(select)和連接(join/union);最常用的函數(distinct/group by/order by等);一些小小的進階技巧(組內排序、取前百分之多少的值、時間函數)。

img

一、最基本(選數據)

img

•怎么把數據從表里選出來?

-- 從table_1中選擇a這一列

select a from table_1

•想要的數據在多張表里,想取多個字段,該怎么辦?—— 表連接

-- table_1中有id,age; table_2中有id,sex。想取出id,age,sex 三列信息

-- 將table_1,table_2 根據主鍵id連接起來

select a.id,a.age,b.sex from

(select id,age from table_1) a --將select之后的內容存為臨時表a

join

(select id, sex from table_2) b --將select之后的內容存為臨時表b

on a.id =b.id

在這里先介紹一下幾種join: (敲重點,很容易問的哦)

img

join :hive的join默認是inner join,找出左右都可匹配的記錄;

img

left join: 左連接,以左表為准,逐條去右表找可匹配字段,如果有多條會逐次列出,如果沒有找到則是NULL;

img

right join:右連接,以右表為准,逐條去左表找可匹配字段,如果有多條會逐次列出,如果沒有找到則是NULL;

img

full outer join:全連接,包含兩個表的連接結果,如果左表缺失或者右表缺失的數據會填充NULL。

img

每種join 都有on , on的是左表和右表中都有的字段。join 之前要確保關聯鍵是否去重,是不是刻意保留非去重結果。

•兩張表數據的字段一樣,想合並起來,怎么辦?

-- 不去重,合並兩張表的數據

select * from

(

select id from table_1

UNION ALL

select id from table_2

)t;

union和union all 均基於列合並多張表的數據,所合並的列格式必須完全一致。union的過程中會去重並降低效率,union all 直接追加數據。union 前后是兩段select 語句而非結果集。

img

二、最常用

img

(不是用這個就是用那個,更有可能多重組合)

為方便大家理解每個函數的作用,先建一個表,后面以這個為示例。

img

•如果有千萬用戶數據,想知道有多少去重的用戶數?—— 去重 distinct

-- 羅列不同的id

select distinct id from table_1

-- 統計不同的id的個數

select count(distinct id) from table_1

-- 優化版本的count distinct

select count(*) from

(select distinct id from table_1) tb

distinct 會對結果集去重,對全部選擇字段進行去重,並不能針對其中部分字段進行去重。使用count distinct進行去重統計會將reducer數量強制限定為1,而影響效率,因此適合改寫為子查詢。

•想分性別進行統計,看看男女各多少?—— 聚合函數和group by

-- 統計不同性別(F、M)中,不同的id個數

select count(distinct id) from table_1

group by sex

-- 其它的聚合函數例如:max/min/avg/sum

-- 統計最大/最小/平均年齡

select max(age), min(age),avg(age) from

table_1

group by id

聚合函數幫助我們進行基本的數據統計,例如計算最大值、最小值、平均值、總數、求和

•只想查看A公司的男女人數數據?—— 篩選 where/having

-- 統計A公司的男女人數

select count(distinct id) from table_1

where company = 'A'

group by sex

-- 統計各公司的男性平均年齡,並且僅保留平均年齡30歲以上的公司

select company, avg(age) from table_1

where sex = 'M'

group by company

having avg(age)>30;

•希望查詢結果從高到低/從低到高排序?—— 排序 order by

-- 按年齡全局倒序排序取最年邁的10個人

select id,age from table_1 order by age DESC

limit 10

•將數值型的變量轉化為分類型的變量? —— case when 條件函數

-- 收入區間分組

select id,

(case when CAST(salary as float)<50000 Then '0-5萬'

when CAST(salary as float)>=50000 and CAST(salary as float)<100000 then '5-10萬'

when CAST(salary as float) >=100000 and CAST(salary as float)<200000 then '10-20萬'

when CAST(salary as float)>200000 then '20萬以上'

else NULL end

from table_1;

case 函數的格式為(case when 條件1 then value1 else null end), 其中else 可以省,但是end不可以省。

在這個例子里也穿插了一個CAST的用法,它常用於string/int/double型的轉換。

•字符串

1.concat( A, B...)返回將A和B按順序連接在一起的字符串,如:concat('foo', 'bar') 返回'foobar'

select concat('www','.iteblog','.com') from

iteblog;

--得到 www.iteblog.com

\2. split(str, regex)用於將string類型數據按regex提取,分隔后轉換為array。

-- 以","為分隔符分割字符串,並轉化為array

Select split("1,2,3",",")as value_array from table_1;

-- 結合array index,將原始字符串分割為3列

select value_array[0],value_array[1],value_array[2] from

(select split("1,2,3",",")as value_array from table_1 )t

\3. substr(str,0,len) 截取字符串從0位開始的長度為len個字符。

select substr('abcde',3,2) from

iteblog;

-- 得到cd

三、基礎進階

•不想全局排序,需要分組排序?—— row_number()

-- 按照字段salary倒序編號

select *, row_number() over (order by salary desc) as row_num from table_1;

-- 按照字段deptid分組后再按照salary倒序編號

select *, row_number() over (partition by deptid order by salary desc) as rank from table_1;

img

按照depid分組,對salary進行排序(倒序)

除了row_number函數之外,還有兩個分組排序函數,分別是rank() 和dense_rank()。

rank()排序相同時會重復,總數不會變 ,意思是會出現1、1、3這樣的排序結果;

dense_rank() 排序相同時會重復,總數會減少,意思是會出現1、1、2這樣的排序結果。

row_number() 則在排序相同時不重復,會根據順序排序。

•想要獲取top10%的值?—— percentile 百分位函數

-- 獲取income字段的top10%的閾值

select percentile(CAST (salary AS int),0.9)) as income_top10p_threshold from table_1;

-- 獲取income字段的10個百分位點

select percentile(CAST (salary AS int),array(0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0)) as income_percentiles

from table_1;

•想要對時間字段進行操作?—— 時間函數

-- 轉換為時間數據的格式

select to_date("1970-01-01 00:00:00") as start_time from table_1;

-- 計算數據到當前時間的天數差

select datediff('2016-12-30','2016-12-29');

-- 得到 "1"

to_date函數可以把時間的字符串形式轉化為時間類型,再進行后續的計算;

常用的日期提取函數包括:

year()/month()/day()/hour()/minute()/second()

日期運算函數包括datediff(enddate,stratdate) 計算兩個時間的時間差(day);

date_sub(stratdate,days) 返回開始日期startdate減少days天后的日期。

date_add(startdate,days) 返回開始日期startdate增加days天后的日期。

四、常見筆試/面試題

例:有3個表S,C,SC:

S(SNO,SNAME)代表(學號,姓名)

C(CNO,CNAME,CTEACHER)代表(課號,課名,教師)

SC(SNO,CNO,SCGRADE)代表(學號,課號,成績)

問題:

1,找出沒選過“黎明”老師的所有學生姓名。

2,列出2門以上(含2門)不及格學生姓名及平均成績。

3,既學過1號課程又學過2號課所有學生的姓名。

\1. -- 考察條件篩選

select sname from s where sno not in

( select sno from sc where cno in

(

select distinct cno from c where cteacher='黎明'

)

);

\2. -- 考察聚合函數,條件篩選

select s.sname, avg_grade from s

join

(select sno from sc where scgrade < 60 group by sno having count(*) >= 2) t1

on s.sno = t1.sno

join

(select sno, avg(scgrade) as avg_grade from sc group by sno ) t2

on s.sno = t2.sno;

\3. -- 考察篩選、連接

select sname from

( select sno from sc where cno = 1) a

join

(select sno from sc where cno = 2) b

on a.sno = b.sno

這篇SQL面試和筆試的入門文章,主旨是快速、清晰的把握重點。希望大家都能快快入門SQL~

轉載連接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM