Ich muss meine Ausgabetabelle partitionieren, wenn eine bestimmte Zeile einen bestimmten Wert hat. Ich habe:

ID|Value|User
-------------
1 |A    |Rick
2 |A    |Rick
3 |B    |Rick
7 |A    |Rick
8 |C    |Rick
4 |A    |Joe
5 |B    |Joe
6 |B    |Joe

Ich muss meine Tabelle für jeden einzelnen Benutzer partitionieren, und wenn der Wert = A ist, brauche ich Folgendes:

Row|ID|Value|User
------------------
1  |1 |A    |Rick 
1  |2 |A    |Rick
2  |3 |B    |Rick
1  |7 |A    |Rick
2  |8 |C    |Rick
1  |4 |A    |Joe
2  |5 |B    |Joe
3  |6 |B    |Joe

Jeder Wert hat eine eigene ID.

Ich habe Dinge ausprobiert wie:

SELECT ROW_NUMBER() OVER(PARTITION BY User, Value = A ORDER BY ID ASC) AS Row, Value, User FROM...
SELECT ROW_NUMBER() OVER(PARTITION BY User, WHERE Value = A ORDER BY ID ASC) AS Row, Value, User FROM...
etc

Aber ich kann nicht herausfinden, wie man es richtig schreibt, wenn es überhaupt möglich ist.

-3
PAT_The_Whale 19 Feb. 2020 im 18:27

3 Antworten

Beste Antwort

Anscheinend ist das, wonach Sie suchen, einfach ein DENSE_RANK:

DENSE_RANK() OVER (PARTITION BY [User] ORDER BY [Value] ASC) AS [Row]

Hinweis USER ist ein reserviertes Schlüsselwort in T-SQL. Ich empfehle Ihnen dringend, einen anderen Namen für Ihre Spalte zu wählen, da Sie ihn ansonsten abgrenzen müssen. ROW und VALUE sind derzeit nicht reserviert, werden jedoch als Future Keyword und deren Verwendung wird ebenfalls empfohlen, um vermieden zu werden.

Bearbeiten: Scheint tatsächlich, dass 'A' 1 ist, und dann auch danach inkrementieren. Das ist chaotisch, aber Sie könnten deshalb tun:

SELECT CASE [Value]
            WHEN 'A' THEN 1
            ELSE ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Value]) -
                 COUNT(CASE [Value] WHEN 'A' THEN 1 END) OVER (PARTITION BY [User]) + 1
       END AS [Row],
       V.[Value],
       V.[User]
FROM (VALUES ('A', 'Rick'),
             ('A', 'Rick'),
             ('B', 'Rick'),
             ('C', 'Rick'),
             ('A', 'Joe '),
             ('B', 'Joe '),
             ('B', 'Joe ')) V ([Value], [User]);

Dies setzt voraus, dass immer mindestens eine Zeile mit 'A' vorhanden ist.

Bearbeiten 2: Ok, Torpfosten wurden wieder verschoben, dies macht jetzt das, wonach Sie suchen. Wenn sie sich erneut bewegen, müssen Sie die Lösung jedoch ändern:

WITH YourTable AS(
    SELECT V.ID,
           V.Value,
           V.[User]
    FROM (VALUES(1,'A','Rick'),
                (2,'A','Rick'),
                (3,'B','Rick'),
                (7,'A','Rick'),
                (8,'C','Rick'),
                (4,'A','Joe '),
                (5,'B','Joe '),
                (6,'B','Joe '))V(ID,[Value],[User])),
Grps AS(
    SELECT YT.ID,
           YT.Value,
           YT.[User],
           COUNT(CASE YT.[Value] WHEN 'A' THEN 1 END) OVER(PARTITION BY YT.[User] ORDER BY YT.ID) AS Grp
    FROM YourTable YT)
SELECT ID,
       CASE G.[Value]
            WHEN 'A' THEN 1
            ELSE ROW_NUMBER() OVER (PARTITION BY G.[User], G.Grp ORDER BY G.[Value]) -
                 COUNT(CASE G.[Value] WHEN 'A' THEN 1 END) OVER (PARTITION BY G.[User], G.Grp) + 1
       END AS [Row],
       G.[Value],
       G.[User]
FROM Grps G
ORDER BY G.[User], G.ID;
1
Larnu 20 Feb. 2020 im 10:20
DECLARE @Table AS TABLE
(
    RowNumber   INT
    ,[Value]    CHAR(5)
    ,[User]     VARCHAR(10)
)

INSERT INTO @Table
(
    [Value]
    ,[User]
)
values
 ('A','Rick') 
,('A','Rick')
,('B','Rick')
,('C','Rick')
,('A','Joe ')
,('B','Joe ')
,('B','Joe ')


    select 
        RowNumber       = DENSE_RANK() OVER(PARTITION BY [User] ORDER BY [Value] ASC) 
        ,[User]
        ,[Value]
    from 
        @Table
    WHERE
        [Value] = 'A'
UNION ALL
    select 
        RowNumber       = ROW_NUMBER() OVER(PARTITION BY [User] ORDER BY [Value] ASC)  + 1
        ,[User]
        ,[Value]
    from 
        @Table
    WHERE
        [Value] != 'A'
    Order BY
        [User] DESC
0
Akash Patel 19 Feb. 2020 im 15:54

Wie wäre es damit - A ist immer 1, ich wickle die Reihe auf 1 zurück, wenn ein A erscheint, dann erhöhe ich immer um 1, wenn es nicht A ist

With CTE AS (select *, row_number() OVER (order by [user], value) as RN from theTable)

select CASE WHEN C1.Value = 'A' THEN 1 ELSE 1 +  C1.RN - C.RN  END [row] ,  * from 
            CTE C1 OUTER APPLY 
              (SELECT TOP 1 RN FROM CTE C2 
                                WHERE C2.RN < C1.RN AND C2.Value = 'A' 
                                ORDER BY C2.RN DESC) C
0
Cato 19 Feb. 2020 im 15:54