1

Je n'ai pas trouvé de fonction permettant de supporter ce que j'essaie d'approcher.SQL Row_Number() (Partition par ... Commande par ...) IGNORES Instruction de commande

Supposons que nous avons le tableau suivant qui contient un ordre de tri sur le terrain et certains doublons

 
+----------+----------+-----+-------------+-----------+ 
| UniqueId | Id | Qty | RetailPrice | SortOrder | 
+----------+----------+-----+-------------+-----------+ 
|  3124 | 92361725 | 25 |  269.99 |   1 | 
|  2627 | 92361725 | 25 |  269.99 |   2 | 
|  7635 | 92361725 | 25 |  269.99 |   3 | 
|  8732 | 92361725 | 25 |  269.99 |   4 | 
|  3791 | 92361725 | 20 |  269.99 |   5 | 
|  4328 | 92361725 | 25 |  269.99 |   6 | 
+----------+----------+-----+-------------+-----------+ 

Je veux énumérer mes lignes augmentant leur valeur quand un doublon, sinon puis réinitialiser le numéro de ligne. Le résultat doit être affiché dans la colonne rn le tableau suivant si Qté est la colonne d'évaluer:

 
+----------+----------+-----+-------------+-----------+----+ 
| UniqueId | Id | Qty | RetailPrice | SortOrder | rn | 
+----------+----------+-----+-------------+-----------+----+ 
|  3124 | 92361725 | 25 |  269.99 |   1 | 1 | 
|  2627 | 92361725 | 25 |  269.99 |   2 | 2 | 
|  7635 | 92361725 | 25 |  269.99 |   3 | 3 | 
|  8732 | 92361725 | 25 |  269.99 |   4 | 4 | 
|  3791 | 92361725 | 20 |  269.99 |   5 | 1 | 
|  4328 | 92361725 | 25 |  269.99 |   6 | 1 | 
+----------+----------+-----+-------------+-----------+----+ 

J'ai essayé d'utiliser ROW_NUMBER() fonction, mais je ne peux pas obtenir les résultats que je veulent-

;WITH Table1 AS(
SELECT 3124 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 1 SortOrder UNION ALL 
SELECT 2627 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 2 SortOrder UNION ALL 
SELECT 7635 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 3 SortOrder UNION ALL 
SELECT 8732 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 4 SortOrder UNION ALL 
SELECT 3791 UniqueId,92361725 Id, 20 Qty, 269.99 RetailPrice, 5 SortOrder UNION ALL 
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 6 SortOrder 
) 

SELECT UniqueId, Id, Qty, RetailPrice, SortOrder, 
ROW_NUMBER() OVER (PARTITION BY Qty ORDER BY SortOrder) rn 
FROM Table1 
 
+----------+----------+-----+-------------+-----------+----+ 
| UniqueId | Id | Qty | RetailPrice | SortOrder | rn | 
+----------+----------+-----+-------------+-----------+----+ 
|  3791 | 92361725 | 20 |  269.99 |   5 | 1 | 
|  3124 | 92361725 | 25 |  269.99 |   1 | 1 | 
|  2627 | 92361725 | 25 |  269.99 |   2 | 2 | 
|  7635 | 92361725 | 25 |  269.99 |   3 | 3 | 
|  8732 | 92361725 | 25 |  269.99 |   4 | 4 | 
|  4328 | 92361725 | 25 |  269.99 |   6 | 5 | 
+----------+----------+-----+-------------+-----------+----+ 

L'Ordre Par est complètement ignorée, quelqu'un peut-il aider?

+5

L'ORDER BY n'est pas ignoré. Si vous partitionnez par Qté, vous regroupez la ligne 6 avec les lignes 1-4. Vous devez essayer une approche "Gaps and Islands". Regardez la fonction LAG. –

+0

Ce n'est pas du tout ignoré. Regardez attentivement. Vous partitionnez le résultat en fonction de la colonne 'Qty'. Par conséquent, dans la première partition, 'rn' est 1. Et dans la partition suivante,' rn' est basé sur 'Qty'. Quoi d'autre voulez-vous? – ViKiNG

+0

Merci tab Alleman mais malheureusement cela doit être abordé en 2008 R2 base de données moteur que je spécifie dans les balises –

Répondre

1

C'est parti. Puisque vous êtes en 2008, j'ai répliqué Lead et Lag en rejoignant ce tableau sur SortOrder +/- 1. J'ai également mis à jour votre jeu d'échantillons pour tenir compte des nouveaux îlots de Qté 25.

Désolé pour le mur de texte mais j'avais pour mettre à jour votre jeu d'échantillons pour ajouter 2 lignes à l'îlot 3 et créer 2 CTE pour obtenir les plages d'îlot.

--Updates Sample Set with 3 Islands. 
WITH Table1 AS(
SELECT 3124 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 1 SortOrder UNION ALL --Island 1 
SELECT 2627 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 2 SortOrder UNION ALL --Island 1 
SELECT 7635 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 3 SortOrder UNION ALL --Island 1 
SELECT 8732 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 4 SortOrder UNION ALL --Island 1 
SELECT 3791 UniqueId,92361725 Id, 20 Qty, 269.99 RetailPrice, 5 SortOrder UNION ALL --Island 2 
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 6 SortOrder UNION ALL --Island 3 
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 7 SortOrder UNION ALL --Island 3 
SELECT 4328 UniqueId,92361725 Id, 25 Qty, 269.99 RetailPrice, 8 SortOrder   --Island 3 
), 

--Creating a CTE to get the Lead and Lag since this is 2008. This will allow us to determine if a row is the first or last row of an island. 
LeadLagTable AS(
SELECT 
    Table1.UniqueId, 
    Table1.Id, 
    Table1.Qty, 
    Table1.RetailPrice, 
    Table1.SortOrder, 
    LeadTable.SortOrder AS LeadSortOrder, 
    LagTable.SortOrder AS LagSortOrder, 
    CASE 
     WHEN LagTable.SortOrder IS NULL THEN 1 
     ELSE 0 
     END AS StartRowFlag, 
    CASE 
     WHEN LeadTable.SortOrder IS NULL THEN 1 
     ELSE 0 
     END AS LastRowFlag 
FROM Table1 
LEFT JOIN Table1 LeadTable ON 
    Table1.SortOrder = LeadTable.SortOrder - 1 
    AND Table1.Qty = LeadTable.Qty 
LEFT JOIN Table1 LagTable ON 
    Table1.SortOrder = LagTable.SortOrder + 1 
    AND Table1.Qty = LagTable.Qty 
), 

--With the LeadLagTable we can now get the ranges for each island, as well as a unique ID for each island. 
Ranges AS (
SELECT 
    RangeStart, 
    RangeEnd, 
    ROW_NUMBER() OVER (ORDER BY RangeStart) AS RangeRowNum 
FROM (
    SELECT 
     StartRow.SortOrder AS RangeStart, 
     EndRow.SortOrder RangeEnd, 
     ROW_NUMBER() OVER (PARTITION BY StartRow.SortOrder ORDER BY EndRow.SortOrder) AS rn 
    FROM LeadLagTable StartRow 
    JOIN LeadLagTable EndRow ON 
     StartRow.StartRowFlag = 1 
     AND EndRow.LastRowFlag = 1 
     AND StartRow.SortOrder <= EndRow.SortOrder 
     AND StartRow.Qty = EndRow.Qty 
    ) tbl 
WHERE rn = 1 
) 

Et voici la requête actuelle.

--We now join on the island ranges, and partition by the Island ID. 
SELECT 
    UniqueId, 
    Id, 
    Qty, 
    RetailPrice, 
    SortOrder, 
    ROW_NUMBER() OVER (PARTITION BY RangeRowNum ORDER BY SortOrder) AS rn 
FROM Table1 
LEFT JOIN Ranges ON 
    Table1.SortOrder >= Ranges.RangeStart 
    AND Table1.SortOrder <= Ranges.RangeEnd 
+0

Je viens de me rendre compte que cela fonctionne avec les données d'échantillon fournies, mais ne pas échelle si vous avez des commandes Qté 25 supplémentaires avec une avance/retard valide. Leur rn continue là où le précédent s'est arrêté. Vérification. –

+0

Mise à jour de la réponse. Cela devrait fonctionner, mais en fonction de la taille de la table, peut nécessiter beaucoup de mémoire. –

+0

Oui, j'ai le scénario complet ici et correspond plutôt bien. Beaucoup de mercis pour les efforts –