全文共3168字,預計學習時長6分鐘
知道如何在SQL內完成基礎操作後(如果不知道,請閱讀「Python SQL基礎簡介」,就可以開始使用SQL提供的更多其他工具了。
GROUP BY語句是SQL中一個很實用的工具。有了它,就可以對數據進行深入研究,並使用一些函數將相同數據進行分組。
如果一欄中不同的行具有相同的值,這些行就會被放到一個單獨的分組中。
使用GROUP BY語句要注意以下重要的三點:
1. GROUP BY 是與SELECT語句一起使用的。
2. 查詢時,GROUP BY位於WHERE語句之後。
3. 查詢時,GROUP BY置於ORDER BY語句之前(如果使用到ORDER BY)。
在了解這些基本規則以後,就可以打開筆記本電腦進行實操了!
設置
以下例子將使用Kaggle數據集中Pokémon遊戲的數據。
儘管使用遊戲數據是為了給SQL增加趣味性,這些例子同樣也非常適用於更加商業化的決策,比如按照年齡段,收入水平,地理位置等給人群進行分組。
首先導入所需的庫,並在python中加載CSV文件。
import pandas as pd
import sqlite3
cnx = sqlite3.connect(':memory:')
csvfile = ('/Users/randy/Documents/GitHub/Pokemon-Stat-Predictor/Pokemon.csv') #Original data
columns = ['#','name','type1','type2','total','hp','attack','defense',\
'sp_atk','sp_def','speed','generation','legendary']
#open the csv file
df = pd.read_csv(csvfile, names=columns, header=0
接下來,先清理數據,然後將其導入SQLite資料庫:
#find NaN values
nan_rows = df[df.isnull().T.any().T]
nan_rows.head()
這一步將會找到所有空值並返回其中一部分(如果有的話)。
當所有空值都出現在type2一欄時,將所有空值都變成「none」。
#change all Type 2 NaN values to 'None':
df['type2'] = df['type2'].fillna('none')
因為SQL對字符串很敏感(同一字符串大寫與小寫代表含義不同),所以要將所有字符都設置為小寫形式。
#change all strings within the dataframe to lower case
df = df.astype(str).apply(lambda x: x.str.lower())
然後將其設置為一個SQL資料庫。
#set the database for pokemon
df.to_sql('pokemon', con=cnx, if_exists='append', index=False)#function for the SQL queries below
def sql_query(query):
return pd.read_sql(query, cnx)
太棒了,接下來可以開始執行一些SQL語句!
GROUP BY的基本語法
GROUP BY函數的基本語法是:
SELECT column_name(s), function_name(column_name)
FROM table_name
WHERE condition
GROUP BY column_name(s)
ORDER BY column_name(s);
function_name: SUM(), AVG(), MIN(), MAX(), COUNT().
table_name: name of the table. In this example, there is only the pokemon table
condition: condition used.
有了它,就可以重新組織和操作數據,以得到更好的分析。
簡單的GROUP BY語句
如果只想得到Pokémon中能力最高的那個精靈的名稱,類別與總能力值,可以以一個簡單的MAX()查詢開始:
query = '''
SELECT name, type1, type2, MAX(total)
FROM pokemon
WHERE legendary = 'true';
'''
sql_query(query)
這個操作將輸出超級Mewtwo X,一個同時具有精神與戰鬥屬性,總能力值高達780的Pokémon。
但如果只想要了解type1種類下能力最強的Pokémon呢?GROUP BY語句在這時就展現出其用武之地了:
query = '''
SELECT name, type1, type2, MAX(total)
FROM pokemon
WHERE legendary = 'true'
GROUP BY type1;
'''
sql_query(query)
現在輸出的就不只是一個Pokémon(超級Mewtwo X)了,而是14個傳奇的小精靈。
SQL查詢找到了所有傳奇小Pokémon,並基於type1欄將它們分到了單獨的組中。
Pokémon在被分到了暗系、龍系、電系、飛行系等不同的組後,SQL查詢將返回每一個組中小Pokémon的名字、type1、type2與總能力值。
GROUP BY和HAVING語句
WHERE語句能給各欄加設條件,但如果想要給組加設條件呢?引入HAVING語句!
由於WHERE關鍵詞不能用在聚合函數中,在此選用帶有GROUP BY的HAVING語句。
可以用HAVING語句輸入條件來決定哪一組將會成為最終結果的一部分。同樣的, WHERE語句對聚合函數不起任何作用。所以如果想要加設條件,就要將HAVING語句用於聚合函數中。
HAVING語句的基本語法:
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);
帶有HAVING語句的GROUP BY
如果想知道所有Pokémon的數量、type1、最小和最大總能力值與所有type1分組下小Pokémon的平均HP,且只包含那些總HP值高於4000的Pokémon組:
query = '''
SELECT COUNT(name) as pokemon_count, type1, MIN(total), MAX(total), AVG(HP)
FROM pokemon
GROUP BY type1
HAVING SUM(HP) > 4000;
'''
sql_query(query)
這有助於確定哪些小Pokémon組在其類別中具有最高的HP值,同時也能剔除事先設定好的HP小於4000的Pokémon組。
如果想從具有高HP值的小Pokémon裡進行挑選,最好選擇普通type1組,其中的小精靈具有最高平均HP值(77.28)且非常耐打。
HAVING語句真的有助於精簡數據,並得出更有用更深刻的結果。
留言 點讚 關注
我們一起分享AI學習與發展的乾貨
如需轉載,請後臺留言,遵守轉載規範