J'ai essayé de trouver des informations sur la manière de sélectionner une colonne non agrégée qui ne figure pas dans l'instruction Group By en SQL, mais rien de ce que j'ai trouvé jusqu'à présent ne semble répondre à ma question. J'ai une table avec trois colonnes que je veux en tirer. L'une est une date de création, l'autre est un ID qui regroupe les enregistrements en fonction d'un ID de revendication particulier et la dernière est la PK. Je souhaite rechercher l’enregistrement qui a la date de création maximale dans chaque groupe d’ID de revendication. Je sélectionne le MAX (date de création), l'ID de revendication (cpe.fmgcms_cpeclaimid) et le regroupement par l'ID de revendication. Mais j'ai besoin du PK de ces enregistrements (cpe.fmgcms_claimid), et si j'essaie de l'ajouter à ma clause select, j'obtiens une erreur. Et je ne peux pas l'ajouter à mon article groupe par article, car cela annulera le regroupement auquel il est destiné. Est-ce que quelqu'un connaît des solutions de contournement pour cela? Voici un exemple de mon code:
Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid
Voici le résultat que j'aimerais obtenir:
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
Les colonnes du jeu de résultats d’une requête select
avec group by
La clause doit être:
group by
critères, ou ...Donc, vous ne pouvez pas faire ce que vous voulez faire dans une requête simple et simple. La première chose à faire est d’énoncer clairement l’énoncé de votre problème, par exemple:
Je souhaite trouver la ligne de revendication individuelle portant la date de création la plus récente dans chaque groupe de mon tableau de revendications.
Donné
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 ) ,
)
La première chose à faire est d’identifier la date de création la plus récente pour chaque groupe:
select group_id ,
date_created = max( date_created )
from dbo.claims_table
group by group_id
Cela vous donne les critères de sélection dont vous avez besoin (1 ligne par groupe, avec 2 colonnes: ID_groupe et la date de création haute heure) pour répondre à la 1ère partie de l'exigence (sélection de la ligne individuelle dans chaque groupe. Il doit s'agir d'une table virtuelle dans votre dernière requête 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
Si la table n'est pas unique par date_created
dans les group_id
_ (AK02), vous pouvez obtenir des lignes en double pour un groupe donné.
Vous pouvez le faire avec PARTITION
et 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
La réponse directe est que vous ne pouvez pas. Vous devez sélectionner un agrégat ou un élément que vous regroupez.
Donc, vous avez besoin d'une approche alternative.
1). Prenez votre requête actuelle et joignez les données de base dessus
SELECT
cpe.*
FROM
Filteredfmgcms_claimpaymentestimate cpe
INNER JOIN
(yourQuery) AS lookup
ON lookup.MaxData = cpe.createdOn
AND lookup.fmgcms_cpeclaimid = cpe.fmgcms_cpeclaimid
2) Utilisez un CTE pour tout faire en une fois ...
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
REMARQUE: L'utilisation de ROW_NUMBER()
ne garantit qu'un seul enregistrement par fmgcms_cpeclaimid
. Même si plusieurs enregistrements sont liés avec exactement la même valeur createdon
. Si vous pouvez avoir des liens et que vous voulez que tous les enregistrements aient la même valeur createdon
, utilisez plutôt RANK()
.
Vous pouvez join
la table sur elle-même pour obtenir le 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'
Ce que vous demandez, Monsieur, est la réponse de RedFilter. Cette réponse aide également à comprendre pourquoi group by est en quelque sorte une version ou partition plus simple: SQL Server: Différence entre PARTITION BY et GROUP BY puisqu’elle modifie le mode de calcul de la valeur renvoyée. (en quelque sorte) renvoient groupe de colonnes par ne peut pas retourner.