group by 和 聚合函數的使用


有這樣一個表數據:

學生姓名,學生手機號,上課日期,上課科目

 

科目分:

語文、數學、英語、計算機

 

要求統計一個這樣子的結果:

學生姓名,學生手機號,第一次上課日期,迄今一共上了多少節課,上的最多的科目是,該科目一共上了幾節

 

本來想着簡單,那不就是group by一下,一個子查詢l不就解決了,想法如下:

select 學生姓名,學生手機號,min(上課日期),上課科目,count(上課科目) as 該科目一共上了幾節  form 表 group by 學生姓名,學生手機號,上課科目

 

以上面的查詢結果   as  表2,繼續查詢:

select 學生姓名,學生手機號,min(上課日期),sum(該科目一共上了幾節),max(該科目一共上了幾節),上課科目  form 表2 group by 學生姓名,學生手機號

 

想着,覺得這個max能找到最大數字所在的行,那么順帶返回最大數字那一行的上課科目,結果就出來了。

但是實際運行的時候發現,非聚合項,不能直接查,得使用聚合函數,比如:

這里的 學生姓名,學生手機號 是聚合項,在select的時候可以直接查詢,但是其他的非聚合項,得加上聚合函數,比如這里的 min 、sum 、max ,這些是可以的,
而這個 上課科目 非聚合項,也沒有使用聚合函數,查詢語句會報錯,
想當然的以為會找到最大行對應的上課科目也是不對的,如果真是這樣,那這句sql到底要返回 最小日期 行對應的 上課科目 還是應該返回 最大節數 對應的行里的 上課科目 呢?
不過據說呢mysql的語法是並不嚴謹的,是可以返回這個聚合函數找到的行的其他列數據,不過我並沒有去嘗試驗證。

select
學生姓名,學生手機號min(上課日期),sum(該科目一共上了幾節),max(該科目一共上了幾節)上課科目 form 表2 group by 學生姓名,學生手機號

 

看來偷懶是偷不了了,只好規規矩矩的寫,3級子查詢:

這是一個查詢基表 as 表2 select 學生姓名,學生手機號,min(上課日期) as 單科最小日期,上課科目,count(上課科目) as 單科節數  form 表 group by 學生姓名,學生手機號,上課科目
在基表的基礎上
as 表3 select 學生姓名,學生手機號,min(單科最小日期) as 最小日期,sum(單科節數) as 總節數,max(單科節數) as 最大節數 form 表2 group by 學生姓名,學生手機號 在兩個子查詢的基礎上再查詢,挑出最大節數的數據行,當然,這個最大節數的不一定是單單一個科目,比如,語文、數學都是21節,都是最大節數,那么這個學生就會返回兩行結果 select aaa.學生姓名,aaa. 學生手機號,bbb. 最小日期,bbb. 總節數,aaa. 上課科目,aaa. 單科節數 form 表2 as aaa left join 表3 as bbb on aaa. 學生姓名=bbb. 學生姓名 and aaa. 學生手機號=bbb. 學生手機號 and aaa. 單科節數=bbb. 最大節數

 

來看個實例:

數據:

查詢代碼:

Private Sub 匯總數據()
    
    
    Dim Con As Object, rs As Object

    Set Con = CreateObject("ADODB.Connection")

    Con.Open "Provider=Microsoft.Ace.OLEDB.12.0;Extended Properties='Excel 12.0;hdr=no;imex=1';Data Source=" & ActiveWorkbook.FullName
    

    Dim sql As String, t As String
    
    t = "201902" & "$"
    
    
    Dim table1 As String, table2 As String
    
'    同一個人,同一門課,最小日期,上課次數
    table1 = " SELECT f1, f2, min(f3) as min_f3, f4, count(1) as f4_count from [" & t & "] group by f1,f2,f4 "
    
'    同一個人,最小日期,上最多的次數,一共上多少次課
    table2 = " select f1, f2, min(min_f3) as min_rq, max(f4_count) as f4_max, sum(f4_count) as f4_sum from (" & table1 & ") group by f1,f2 "
    
    
'    姓名    電話    首次上課時間    總上課次數  上得最多的課程(, where left join on 兩種方式都是可以的)
    sql = " SELECT distinct a.f1, a.f2, b.min_rq, b.f4_sum, a.f4, a.f4_count from (" & table2 & ") as b, (" & table1 & ") as a "
    sql = sql & " WHERE a.f1 = b.f1 and a.f2 = b.f2 and a.f4_count = b.f4_max "

'    sql = " SELECT distinct a.f1, a.f2, b.min_rq, b.f4_sum, a.f4, a.f4_count from (" & table2 & ") as b left join (" & table1 & ") as a "
'    sql = sql & " on a.f1 = b.f1 and a.f2 = b.f2 and a.f4_count = b.f4_max "

    Set rs = Con.Execute(sql)
    
    Sheets.Add After:=Sheets(Sheets.Count)
    
    For i = 0 To rs.fields.Count - 1
        Cells(1, i + 1) = rs.fields(i).Name
    Next
    
    Cells(2, 1).CopyFromRecordset rs
    
    rs.Close: Set rs = Nothing
    
    Con.Close: Set Con = Nothing

End Sub

結果: 

 


免責聲明!

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



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