Group by and having clauses

12738 ワード

標準group byとhavingクエリー
  • 選択リストの列もgroupby式に表示するか、集合関数のパラメータでなければなりません.
  • groupby式には、選択リストに表示されるカラム名のみが含まれます.ただし、選択リストで集合関数のパラメータとしてのみ使用されるカラムにはこの制限は適用されません.
  • having式のカラムは、単一の値(たとえば、集合のパラメータ)でなければなりません.また、選択リストまたはgroupby句に表示される必要があります.選択リストセットとhaving句を使用するクエリにはgroup by句が含まれている必要があります.選択リストセットを使用しないクエリーでgroupbyを省略すると、where句で除外されていないすべてのローが単一のグループとみなされます.

  • 非パケットクエリでは、「whereを使用して行を除外する」という原則は非常に簡単です.パケットクエリでは、この原則は「groupbyの前にwhereを使用して行を除外し、havingを使用して表示された結果から行を除外する」に拡張されます.
  • SQL規格では、上記の原則に従う限り、2つ以上のテーブルを接続するクエリーでgroupbyとhavingを使用できます.接続またはその他の複雑なクエリーを指定する場合は、Transact-SQL拡張がこの2つの句に与える影響を完全に理解していない限り、groupbyとhavingの標準構文を使用します.

  • groupbyとhavingのTransact-SQL拡張
    標準SQLのTransact-SQL拡張により、グループや要約計算の作成時に使用されていないカラムや式を参照できるため、データの表示がより柔軟になります.
  • 集合を含む選択リストには、集合関数ではないパラメータとgroupby句に含まれていない拡張列が含まれていてもよい.拡張カラムは、追加のローが表示されるため、最終結果の表示に影響します.
  • groupby句は、選択リストに列挙されていない列または式を含むことができる.
  • groupby all句は、where句によって計算から除外されたすべてのグループを表示します.
  • having句は、選択リストおよびgroupby句に表示されない列または式を含むことができる.

  • Transact-SQL拡張で行または列を表示に追加した場合、またはグループbyを省略した場合、クエリの結果が理解しにくい場合があります.
    インスタンス解析
    One long running SQL in my work. It is a wrong SQL in fact:
  • 問題このSQL文は最後にデカルト積を取り、欲しいように見える内容ではありません
  • SELECT                                                                                                                                                                                                                                                          
         p.party_id,                                                                                                                                                                                                                                                 
         p.party_ticker,                                                                                                                                                                                                                                             
         p.party_rtr_ticker,                                                                                                                                                                                                                                         
         p.dbs_cid,                                                                                                                                                                                                                                                  
         p.party_cntry_incorp_cd,                                                                                                                                                                                                                                    
         p.party_long_name,                                                                                                                                                                                                                                          
         p.debt_issued_fl,                                                                                                                                                                                                                                           
         p.party_setup_dt,                                                                                                                                                                                                                                           
         e.last_chg_dt,                                                                                                                                                                                                                                              
         datediff(hour, e.last_chg_dt, getdate() ) AS AGE_in_hours                                                                                                                                                                                                   
     FROM                                                                                                                                                                                                                                                            
         dmo_govcorp..party p, dmo_misc..entity_changed e                                                                                                                                                                                                            
     where     e.obj_oid = p.party_id                                                                                                                                                                                                                                
           AND e.obj_type_cd = 'GCPA'                                                                                                                                                                                                                                
     GROUP BY                                                                                                                                                                                                                                                        
         p.party_rtr_ticker                                                                                                                                                                                                                                          
     HAVING                                                                                                                                                                                                                                                          
         (COUNT(p.party_rtr_ticker)>1) 
    
  • 排解プロセスSQL検出を実行し、Selectリストから2番目のテーブルdmo_を削除misc..entity_changedの項目は、私たちが望む結果を得ることができます.関連ドキュメントを参照すると、selectリストに集合関数ではないパラメータが含まれている場合は、Transact-SQL拡張groupbyであり、クエリがwhere句
  • を無視しているように見える場合があります.
  • 解決We can solve the problemby adding all the conditions in where clauses into having clauses as below to solve it as below:
  • SELECT                                                                                                                                                                                                                                                          
         p.party_id,                                                                                                                                                                                                                                                 
         p.party_ticker,                                                                                                                                                                                                                                             
         p.party_rtr_ticker,                                                                                                                                                                                                                                         
         p.dbs_cid,                                                                                                                                                                                                                                                  
         p.party_cntry_incorp_cd,                                                                                                                                                                                                                                    
         p.party_long_name,                                                                                                                                                                                                                                          
         p.debt_issued_fl,                                                                                                                                                                                                                                           
         p.party_setup_dt,                                                                                                                                                                                                                                           
         e.last_chg_dt,                                                                                                                                                                                                                                              
         datediff(hour, e.last_chg_dt, getdate() ) AS AGE_in_hours                                                                                                                                                                                                   
     FROM                                                                                                                                                                                                                                                            
         dmo_govcorp..party p, dmo_misc..entity_changed e                                                                                                                                                                                                            
     where     e.obj_oid = p.party_id                                                                                                                                                                                                                                
           AND e.obj_type_cd = 'GCPA'                                                                                                                                                                                                                                
     GROUP BY                                                                                                                                                                                                                                                        
         p.party_rtr_ticker                                                                                                                                                                                                                                          
     HAVING                                                                                                                                                                                                                                                          
         (COUNT(p.party_rtr_ticker)>1)  and e.obj_oid = p.party_id and e.obj_type_cd = 'GCPA' 
    
  • Finding統計を開くと、where後の条件をhavingの後に直接加えるのと、先にグループを選択し、selectの文に置くのと同じ効果があることがわかり、両者がデータベース内部で実現するメカニズムは同じであると推測される.

  • 以下は参考資料です.
    selectリストでgroupbyリストにない集合関数を含まない列を使用するのは、Transact-SQL拡張です.拡張カラムは、追加のローが表示されるため、最終結果の表示に影響します.
    Transact-SQL拡張で行または列が表示に追加された場合、クエリの結果が理解しにくい場合があります.Transact-SQL拡張カラムを処理する方法は、クエリがwhere句を無視しているように見える場合があります.例は次のとおりです.
    Adaptive Serverは、まずwhere句を使用してタイプとコレクション値のみを含むワークシートを作成します.このワークシートは、パケット列typeを介してtitlesテーブルに接続され、結果にprice列が含まれますが、where句は使用されません.
    select type, price, avg(price)
    from titles
    where price > 10.00
    group by type
    type price
    ------------ ---------------- --------------
    business 19.99 17.31
    business 11.95 17.31
    business 2.99 17.31
    business 19.99 17.31
    mod_cook 19.99 19.99
    mod_cook 2.99 19.99
    popular_comp 22.95 21.48
    popular_comp 20.00 21.48
    popular_comp NULL 21.48
    psychology 21.59 17.51
    psychology 10.95 17.51
    psychology 7.00 17.51
    psychology 19.99 17.51
    psychology 7.99 17.51
    trad_cook 20.95 15.96
    trad_cook 11.95 15.96
    trad_cook 14.99 15.96
    (17 rows affected)
    

    $10.00未満の価格の行を表示結果で除去するには、where句を繰り返すhaving句を追加する必要があります.
    select type, price, avg(price)
    from titles
    where price > 10.00
    group by type
    having price > 10.00
    type price
    ----------- ---------------- --------------
    business 19.99 17.31
    business 11.95 17.31
    business 19.99 17.31
    mod_cook 19.99 19.99
    popular_comp 22.95 21.48
    popular_comp 20.00 21.48
    psychology 21.59 17.51
    psychology 10.95 17.51
    psychology 19.99 17.51
    trad_cook 20.95 15.96
    trad_cook 11.95 15.96
    trad_cook 14.99 15.96
    (12 rows affected)
    

    参考文献:Sybaseリファレンスマニュアル:コマンドAdaptive Server® Enterprise 15.0