web-dev-qa-db-ja.com

Group ByにないSQLの列を選択する

SQLのGroup Byステートメントに含まれていない非集計列を選択する方法に関する情報を見つけようとしてきましたが、これまでのところ何も私の質問に答えていないようです。 3つの列があるテーブルがあります。 1つは作成日、1つは特定のクレームIDでレコードをグループ化するID、最後はPKです。クレームIDの各グループで最大作成日を持つレコードを見つけたい。 MAX(作成日)とクレームID(cpe.fmgcms_cpeclaimid)を選択し、クレームIDでグループ化しています。しかし、これらのレコード(cpe.fmgcms_claimid)からPKが必要であり、それを選択句に追加しようとすると、エラーが発生します。また、意図したグループ化が無効になるため、group by句に追加できません。誰かがこれの回避策を知っていますか?これが私のコードのサンプルです:

Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid 
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid

これは私が取得したい結果です:

Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid, cpe.fmgcms_claimid 
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid
44
user1603734

group by句を含むselectクエリの結果セットの列は次のとおりである必要があります。

  • group by基準の1つとして使用される式、または...
  • 集約関数、または...
  • リテラル値

そのため、1つの簡単なクエリでやりたいことを実行できません。最初に行うことは、次のような明確な方法で問題のステートメントを述べることです。

クレームテーブルで各グループ内の最新の作成日を含む個々のクレーム行を検索したい

与えられた

create table dbo.some_claims_table
(
  claim_id     int      not null ,
  group_id     int      not null ,
  date_created datetime not null ,

  constraint some_table_PK primary key ( claim_id                ) ,
  constraint some_table_AK01 unique    ( group_id , claim_id     ) ,
  constraint some_Table_AK02 unique    ( group_id , date_created ) ,

)

最初に行うことは、各グループの最新の作成日を識別することです。

select group_id ,
       date_created = max( date_created )
from dbo.claims_table
group by group_id

これにより、要件の最初の部分を完全に満たすために必要な選択基準(グループごとに1行、2列:group_idとhighwater作成日)が得られます(各グループから個々の行を選択します。最終的なselectクエリ:

select *
from dbo.claims_table t
join ( select group_id ,
       date_created = max( date_created )
       from dbo.claims_table
       group by group_id
      ) x on x.group_id     = t.group_id
         and x.date_created = t.date_created

テーブルがdate_created(AK02)内のgroup_idによって一意でない場合、特定のグループの行を重複して取得できます。

37
Nicholas Carey

PARTITIONおよびRANKを使用してこれを行うことができます。

select * from
(
    select MyPK, fmgcms_cpeclaimid, createdon,  
        Rank() over (Partition BY fmgcms_cpeclaimid order by createdon DESC) as Rank
    from Filteredfmgcms_claimpaymentestimate 
    where createdon < 'reportstartdate' 
) tmp
where Rank = 1
17
RedFilter

直接的な答えは、できないということです。 must集約またはグループ化するものを選択します。

そのため、別のアプローチが必要です。

1)。現在のクエリを取得し、ベースデータを結合します

_SELECT
  cpe.*
FROM
  Filteredfmgcms_claimpaymentestimate cpe
INNER JOIN
  (yourQuery) AS lookup
    ON  lookup.MaxData           = cpe.createdOn
    AND lookup.fmgcms_cpeclaimid = cpe.fmgcms_cpeclaimid
_

2)。 CTEを使用して、すべてを一度に実行します...

_WITH
  sequenced_data AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARITION BY fmgcms_cpeclaimid ORDER BY CreatedOn DESC) AS sequence_id
  FROM
    Filteredfmgcms_claimpaymentestimate
  WHERE
    createdon < 'reportstartdate'
)
SELECT
  *
FROM
  sequenced_data
WHERE
  sequence_id = 1
_

注:ROW_NUMBER()を使用すると、_fmgcms_cpeclaimid_ごとに1つのレコードのみが確保されます。複数のレコードがまったく同じcreatedon値で結び付けられている場合でも。同順位ができ、同じcreatedon値を持つすべてのレコードが必要な場合は、代わりにRANK()を使用します。

8
MatBailie

テーブル自体をjoinしてPKを取得できます:

Select cpe1.PK, cpe2.MaxDate, cpe1.fmgcms_cpeclaimid 
from Filteredfmgcms_claimpaymentestimate cpe1
INNER JOIN
(
    select MAX(createdon) As MaxDate, fmgcms_cpeclaimid 
    from Filteredfmgcms_claimpaymentestimate
    group by fmgcms_cpeclaimid
) cpe2
    on cpe1.fmgcms_cpeclaimid = cpe2.fmgcms_cpeclaimid
    and cpe1.createdon = cpe2.MaxDate
where cpe1.createdon < 'reportstartdate'
3
Taryn

あなたが求めているのは、レッドフィルターの答えです。この回答は、group byが何らかの理由でより単純なバージョンまたはパーティションである理由を理解するのにも役立ちます: SQL Server:PARTITION BYとGROUP BYの違い (どういうわけか)列をグループ化して返すことはできません。

1
Eyad Ebrahim