/ / Comment sélectionner ou passer à la ligne suivante si certains critères sont remplis - SQL, serveur SQL, tsql, classement

Comment sélectionner ou passer à la prochaine ligne si certains critères sont remplis - sql, sql-server, tsql, ranking

Je ne suis vraiment pas sûr de la direction à prendre pour cela ... J'essaie de sélectionner une liste de clients en fonction des règles suivantes:

  • Sélectionnez toutes les lignes de Client où Classement = 1,

  • OU si Ranking = 1 AND Type = Store puis Rank 1 et renvoie la ligne avec le rang 2.

  • OU si le client n'a qu'une seule ligne, retournez-la même si le type = Store.

Le classement n'est pas affecté d'une déclaration de classement dans la requête. Il s’agit plutôt d’une colonne réelle de la table Client (renseignée par un proc stocké qui effectue le classement).

En utilisant l’exemple ci-dessous, je voudrais que les lignes 1, 4, 6 et 10 soient renvoyées.

Tableau client

RowID   CustID  Type    Ranking

-----   ------  ----    -------

1       9       Web      1
2       9       Catalog  2
3       9       Store    3
4       10      Store    1
5       11      Store    1
6       11      Web      2
7       12      Store    1
8       12      Web      2
9       12      Catalog  3
10      13      Web      1

J'ai l'impression que cette tâche est plus difficile parce que le classement est déjà fait lorsque la table est créée! Toutes les suggestions sont les bienvenues!

Réponses:

1 pour la réponse № 1

Vous pouvez essayer quelque chose comme ça (je ne l’ai pas testé!):

SELECT
RowId,
CustId,
Type,
Ranking
FROM Customer c
WHERE (c.Ranking = 1 AND c.Type != "Store")
OR (c.Type = "Store" AND Ranking = 2)
OR (c.Type = "Store" AND Ranking = 1 AND NOT EXISTS (SELECT 1 FROM Customer WHERE CustId = c.CustId AND Ranking = 2))

Si la table des clients est volumineuse, vous pourriez trouver que la requête est un peu lente et quelque chose comme ça serait plus rapide:

SELECT
RowId,
CustId,
Type,
Ranking
FROM Customer c
WHERE c.Ranking = 1 AND c.Type != "Store"

UNION ALL

SELECT
RowId,
CustId,
Type,
Ranking
FROM Customer c
WHERE c.Type = "Store" AND Ranking = 2

UNION ALL

SELECT
RowId,
CustId,
Type,
Ranking
FROM Customer c
WHERE c.Type = "Store" AND Ranking = 1 AND NOT EXISTS (SELECT 1 FROM Customer WHERE CustId = c.CustId AND Ranking = 2)

0 pour la réponse № 2

Comme pour l'autre réponse, je n'ai pas fait beaucoup dedes tests approfondis, mais voici ce que je regarderais. L'idée ici est de créer un row_number sur le type de priorité de l'ensemble de données: stocker en haut, puis en utilisant rank comme condition de tri secondaire.

select *
from (
select
rid = row_number() over  (partition by CustID, order by case when type = "Store" then 0 else 1 end, Rank desc),
rowid,
CustID,
Type,
Ranking
from customer)
where RID = 1

0 pour la réponse № 3

Essayer:

SELECT *
FROM Customer c
WHERE
-- There"s only one row for this customer
(
SELECT COUNT(*)
FROM Customer
WHERE CustID = c.CustID
) = 1
-- There"s a row with Ranking = 1 and Type = "Store", so select Ranking = 2
OR (Ranking = 2 AND EXISTS (SELECT 1 FROM Customer WHERE CustID = c.CustID AND Ranking = 1 AND Type = "Store"))
-- There"s a row with Ranking = 1 that"s not Type = "Store"
OR (Ranking = 1 AND Type <> "Store")