7
votes

Choisir une rangée sur un autre

J'ai une table qui ressemble à ceci: xxx

pour chaque identifiant, je voudrais récupérer une valeur. Idéalement, la valeur devrait venir de la ligne avec type Z01. Cependant, si Z01 n'est pas disponible, je choisirai la Z09 à la place. Si rien n'est disponible, je voudrais ne rien sélectionner.

Le résultat ressemblerait à ceci: xxx

Comment puis-je accomplir cela avec T-SQL?


1 commentaires

Désolé, cela était censé être dans la table d'origine. Corrigé-le maintenant.


6 Réponses :


5
votes

Cela devrait vous donner ce que vous voulez: xxx

une alternative, avec une approche plus courante, c'est (réécrire le cas expression ): xxx

Une approche évidente Sargable (qui permettra à votre requête d'utiliser l'index approprié sur votre table, si elle existe) serait: < Pré> xxx

et quand je dis index, je parle d'un index non clusterné sur la colonne .


7 commentaires

C'est un moyen compliqué d'aborder le problème. Une expression de cas n'appartient pas à un clause. Utilisez et , ou et entre parenthèses à la place.


@Thorstenkettner pourrait être, mais je suppose qu'ils sont les mêmes identiques. Et pourquoi l'expression appartient-elle dans un où la clause ? Je suis curieux si vous en avez des exemples pour cela.


C'est aussi un non sargable Query et aura une très mauvaise performance.


@Erikphilipips basé sur quelles règles ma requête devient-elle non sargable? Malheureusement (pour moi), je ne vois pas pourquoi c'est. Est-ce à cause du ou ?


Bonjour, comme vous l'avez montré avec votre deuxième requête, vous pouvez écrire n'importe quelle expression booléenne dans et c'est plus simple. Il n'y a pas besoin d'une construction qui vous permet de créer une valeur d'une expression booléenne dans . Case est effectué pour le Sélectionnez et Commandez par Les clauses permettent d'évaluer une expression booléenne là-bas.


@RADUGHEORGHIU Votre message original avec seulement la requête utilisée par la déclaration de cas nécessite une analyse de cas pour chaque ligne, ce qui signifie qu'il est non sargable.


@Erikphilips Même donc, il n'ya presque aucun moyen de garantir un indice de recherche sans en savoir plus sur la structure de la table. Mais, en termes d'utilisation de l'indice, s'il existe un indice sur la colonne , une approche utilisera définitivement (même s'il s'avère être une analyse d'index).



0
votes

Vous pouvez utiliser une requête comme celle-ci

;WITH cte
AS (SELECT
    *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) AS rn
FROM yourtable
WHERE type IN ('Z01', 'Z09'))
SELECT
    id, type, value
FROM cte
WHERE rn = 1


0 commentaires

0
votes

Je voudrais utiliser les fonctions de fenêtre:

select t.*
from (select t.*,
             row_number() over (partition by id order by type) as seqnum
      from t
      where type in ('Z01', 'Z09')
     ) t
where seqnum = 1;


0 commentaires

0
votes

Essayez ensuite cette

 Select distinct a.id, 
    coalesce(t1.type, t9.type) type,
    case when t1.type is not null 
         then t1.value else t9.value end value
 From table a 
    left join table t1 
       on t1.id = a.id 
          and t1.type = 'Z01'
    left join table t9 
       on t9.id = a.id 
          and t9.type = 'Z09'
  Where a.type in ('Z01', 'Z09')  -- < -- this last to eliminate row E


0 commentaires

0
votes

quelque chose comme ceci:

select distinct
base.Id,
Coalesce(z01.Type, any.Type) Type,
Coalesce(z01.Value, any.Value)
from (select distinct id from [table]) base
left outer join [table] z01
    on z01.id = base.id
    and z01.Type = 'Z01'
left outer join [table] any
    on any.id = base.id
    and any.type != 'Z01'


0 commentaires

0
votes

Démarrer avec un où code> clause. Sélectionnez uniquement les entrées avec Z01 et Z09. Ensuite, utilisez row_number code> pour classer vos lignes et garder le meilleur.

select id, type, value 
from
(
    select 
      id, type, value, 
      row_number() 
        over (partition by id order by case when type = 'Z01' then 1 else 2 end) as rn
    from mytable
    where type in ('Z01','Z09')
) ranked
where rn = 1;


0 commentaires