2017-11-20 1 views
5

habe ich eine Teilmenge einer SQL Server 2008 R2 Tabelle wie folgt aus:Rang Tabelle auf eine Spalte, während das Sortieren auf einem anderen

cust_id | prod_id | day | price 
--------+---------+-----+------- 
137656 194528 42373 9.11 
137656 194528 42374 9.11 
137656 194528 42375 9.61 
137656 194528 42376 9.61 
137656 194528 42377 9.11 
137656 194528 42378 9.11 

Ich brauche die unterschiedlichen Preisperioden wie so Rang:

cust_id | prod_id | day | price | rank 
--------+---------+-----+-------+------ 
137656 194528 42373 9.11  1 
137656 194528 42374 9.11  1 
137656 194528 42375 9.61  2 
137656 194528 42376 9.61  2 
137656 194528 42377 9.11  3 
137656 194528 42378 9.11  3 

so dass es sortiert nach cust_id, prod_id und day aufsteigend aber erhöht den Rang, wenn die Preisänderungen. Ich habe versucht, DENSE_RANK() wie folgt zu verwenden:

SELECT 
    cust_id, prod_id, [day], price, 
    DENSE_RANK() OVER (ORDER BY cust_id, prod_id, price) 
FROM 
    @prices 

Das gibt so etwas wie:

cust_id | prod_id | day | price | rank 
--------+---------+-----+-------+------ 
137656 194528 42373 9.11  1 
137656 194528 42374 9.11  1 
137656 194528 42377 9.11  1 
137656 194528 42378 9.11  1 
137656 194528 42375 9.61  2 
137656 194528 42376 9.61  2 

Offensichtlich den Tag von der Art ohne gibt mir diese Ergebnisse aber wenn ich schließen Sie den Tag in der Reihenfolge von Abschnitt der DENSE_RANK() - es partitioniert einfach jeden neuen Tag als eine neue ID ....

Hat jemand irgendwelche Ideen, wie dies funktionieren sollte? Freuen uns über jede Beratung und kann weitere Informationen geben, wenn

erforderlich
+0

Nur als eine Anmerkung, versuchte ich, den [Unterschied in Zeilennummer-Methode] (http://rextester.com/COMB14371), aber es ist fehlgeschlagen, also ist dies wahrscheinlich kein guter Ansatz. –

+0

Wie wird der Rang geändert, wenn cust_id oder prod_id geändert wird? Es wäre besser, wenn Sie das auch in Ihrer Probe hinzufügen würden. –

Antwort

1

Die erste Variante mit LAG und SUM

SELECT 
    *, 
    1+SUM(IncCount)OVER(PARTITION BY cust_id ORDER BY [day]) [rank] 
    --1+SUM(IncCount)OVER(PARTITION BY cust_id ORDER BY [day] ROWS BETWEEN unbounded preceding AND current row) [rank] 
FROM 
    (
    SELECT 
     *, 
     IIF(LAG(price)OVER(PARTITION BY cust_id ORDER BY [day])<>price,1,0) IncCount 
     --CASE WHEN LAG(price)OVER(PARTITION BY cust_id ORDER BY [day])<>price THEN 1 ELSE 0 END IncCount 
    FROM Test 
) q 

Die zweite Variante ohne LAG

WITH numCTE AS(
    SELECT *,ROW_NUMBER()OVER(PARTITION BY cust_id ORDER BY [day]) RowNum 
    FROM Test 
) 
SELECT 
    t1.*, 
    1+SUM(CASE WHEN t2.price<>t1.price THEN 1 ELSE 0 END)OVER(PARTITION BY t1.cust_id ORDER BY t1.[day]) [rank] 
    --1+SUM(CASE WHEN t2.price<>t1.price THEN 1 ELSE 0 END)OVER(PARTITION BY t1.cust_id ORDER BY t1.[day] ROWS BETWEEN unbounded preceding AND current row) [rank] 
FROM numCTE t1 
LEFT JOIN numCTE t2 ON t2.RowNum+1=t1.RowNum AND t2.cust_id=t1.cust_id 

Die dritte Variante mit rekursiven CTE

WITH numCTE AS(
    SELECT *,ROW_NUMBER()OVER(PARTITION BY cust_id ORDER BY [day]) RowNum 
    FROM Test 
), 
rankCTE AS(
    SELECT RowNum,cust_id,prod_id,[day],price,1 [rank] 
    FROM numCTE 
    WHERE RowNum=1 

    UNION ALL 

    SELECT 
    n.RowNum,n.cust_id,n.prod_id,n.[day],n.price, 
    r.[rank]+CASE WHEN n.price<>r.price THEN 1 ELSE 0 END [rank] 
    FROM numCTE n 
    JOIN rankCTE r ON n.RowNum=r.RowNum+1 AND n.cust_id=r.cust_id 
) 
SELECT * 
FROM rankCTE 
OPTION(MAXRECURSION 0) 
+0

Danke dafür, es sieht so aus, als würde es funktionieren, aber leider funktioniert LAG nicht auf einer SQL 2008 R2 Datenbank, ich hätte das in der ersten Frage erwähnen sollen, ich habe es jetzt aktualisiert - Entschuldigung! – samil90

+0

Versuchen Sie die zweite Variante. Ich hoffe, es funktioniert in SQLServer 2008. – Leran2002

+0

Danke, ich habe beide zuletzt genannten Optionen getestet. Option 2 gibt mir eine 2 für die erste Zeile des neuen Preises, kehrt dann aber wieder zu 1 zurück - was es schwierig macht, nach dieser ID zu gruppieren und einen Min- und Max-Tag zu erhalten, um eine Preisspanne anzugeben. Option 3 ist besser, da es mir einen inkrementellen Rang für jeden neuen Preis gibt, aber die verschiedenen cust_ids nicht berücksichtigt. – samil90

Verwandte Themen