Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL Server, encontre uma sequência arbitrária de valores


Isso selecionará todos os clientes com pelo menos duas ações consecutivas do mesmo tipo.
WITH    rows AS 
        (
        SELECT  customer, action,
                ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
        FROM    mytable
        )
SELECT  DISTINCT customer
FROM    rows rp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    rows rl
        WHERE   rl.customer = rp.customer
                AND rl.rn = rp.rn + 1
                AND rl.action = rp.action
        )

Aqui está a consulta mais eficiente para apenas a ação 2 :
WITH    rows AS 
        (
        SELECT  customer, ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
        FROM    mytable
        WHERE   action = 2
        )
SELECT  DISTINCT customer
FROM    rows rp
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    rows rl
        WHERE   rl.customer = rp.customer
                AND rl.rn = rp.rn + 1
        )

Atualização 2:

Para selecionar intervalos ininterruptos:
WITH    rows AS 
        (
        SELECT  customer, action, lastlogin
                ROW_NUMBER() OVER (PARTITION BY customer ORDER BY lastlogin) AS rn
                ROW_NUMBER() OVER (PARTITION BY customer, action ORDER BY lastlogin) AS series
        FROM    mytable
        )
SELECT  DISTINCT customer
FROM    (
        SELECT  customer
        FROM    rows rp
        WHERE   action
        GROUP BY
                customer, actioncode, series - rn
        HAVING
                DETEDIFF(day, MIN(lastlogin), MAX(lastlogin)) >= 14
        ) q

Esta consulta calcula duas séries:uma retorna ORDER BY lastlogin contígua , o segundo particiona por action Além disso:
action  logindate rn  series diff = rn - series
1       Jan 01    1   1      0
1       Jan 02    2   2      0
2       Jan 03    3   1      2
2       Jan 04    4   2      2
1       Jan 05    5   3      2
1       Jan 06    6   4      2

Enquanto a diferença entre os dois esquemas for a mesma, as séries são ininterruptas. Cada interrupção quebra a série.

Isso significa que a combinação de (action, diff ) define os grupos ininterruptos.

Podemos agrupar por action, diff , encontre MAX e MIN dentro dos grupos e filtrá-los.

Se você precisar selecionar 14 linhas em vez de 14 dias consecutivos, basta filtrar por COUNT(*) em vez do DATEDIFF .