2017-10-05 2 views
1

J'ai un problème avec SQL. J'ai le tableau suivant:Rotation des clients dans SQL Server 2014

declare @t table (date datetime, 
      shop VARCHAR(50), 
      client VARCHAR(50) 
     ); 
insert into @t 
VALUES ('2016-01-15', 'abc','a1'), 
     ('2016-01-15', 'abc','b1'), 
     ('2016-01-15', 'def','c1'), 
     ('2016-01-15', 'def','a1'), 
     ('2016-01-15', 'ghi','b1'), 
     ('2016-01-15', 'ghi','a1'), 
     ('2016-02-15', 'abc','a1'), 
     ('2016-02-15', 'abc','b1'), 
     ('2016-02-15', 'abc','c1'), 
     ('2016-02-15', 'def','a1'), 
     ('2016-02-15', 'ghi','b1'), 
     ('2016-02-15', 'ghi','a1'), 
     ('2016-03-15', 'abc','a1'), 
     ('2016-03-15', 'abc','c1'), 
     ('2016-03-15', 'def','a1'), 
     ('2016-03-15', 'ghi','b1'), 
     ('2016-03-15', 'ghi','e1') 

Je voudrais calculer la rotation du client. Donc, pour chaque mois, pour chaque magasin, il faut compter le nombre de clients qui sont arrivés, et combien de clients sont restés comme le mois précédent. Je ne peux pas simplement regarder le nombre de clients, mais je dois vérifier si le nom spécifique du client est apparu un mois plus tôt. Toutes les dates ressemblent à ceci: "année-mois-15".

Je voudrais obtenir le tableau comme suit:

declare @t2 table (date date, 
       shop VARCHAR(50), 
       churned INTEGER, 
       stayed INTEGER, 
       came INTEGER 
      ); 

INSERT INTO @t2 
VALUES ('2016-02-15', 'abc', 0, 2, 1), 
    ('2016-02-15', 'def', 1, 1, 0), 
    ('2016-02-15', 'ghi', 0, 2, 0), 
    ('2016-03-15', 'abc', 1, 2, 0), 
    ('2016-03-15', 'def', 0, 1, 0), 
    ('2016-03-15', 'ghi', 1, 1, 1) 

Ainsi, par exemple pour le magasin abc après le premier mois 0 clients brassés, 2 clients sont restés comme mois avant et 1 nouveau client est venu. Baratté signifie que le client est parti.

Merci pour votre aide. J'utilise SQL Server 2014

EDIT: Un autre exemple: Pour ces données:

declare @t table (date datetime, 
shop VARCHAR(50), 
client VARCHAR(50) 
    ); 
    insert into @t 
    VALUES ('2016-01-15', 'abc','a1'), 
    ('2016-01-15', 'abc','b1'), 

    ('2016-02-15', 'abc','b1'), 
    ('2016-02-15', 'abc','c1'), 

    ('2016-03-15', 'abc','z1'), 
    ('2016-03-15', 'abc','y1'), 
    ('2016-03-15', 'abc','a1') 

je devrais obtenir le tableau suivant:

declare @t2 table (date date, 
      shop VARCHAR(50), 
      churned INTEGER, 
      stayed INTEGER, 
      came INTEGER 
     ); 

    INSERT INTO @t2 
    VALUES 
    ('2016-01-15', 'abc', 0, 0, 2), 
    ('2016-02-15', 'abc', 1, 1, 1), 
    ('2016-03-15', 'abc', 2, 0, 3) 

C'est par exemple simple avec une seule magasiner pour une clarification.

+0

définissent "baratte" s'il vous plaît. – Tanner

+0

Cet homme que le client a quitté. –

Répondre

1

vous pouvez essayer cette

SELECT 
    ISNULL(T1.date, DATEADD(MONTH,1,T2.date)) date, 
    ISNULL(T2.shop,T1.shop) shop, 
    COUNT(CASE WHEN T1.client IS NULL THEN 1 END) churned, 
    COUNT(case when (T1.client = T2.client) then 1 end) stayed, 
    COUNT(CASE WHEN T2.client IS NULL THEN 1 END) came 
FROM 
    @t T1 
    FULL JOIN @t T2 ON MONTH(T1.date) - 1 = MONTH(T2.[date]) 
      AND T1.client = T2.client AND T1.shop = T2.shop 
GROUP BY 
    ISNULL(T1.date, DATEADD(MONTH,1,T2.date)) ,ISNULL(T2.shop,T1.shop) 
ORDER BY [date], shop 
+0

Désolé mais cela ne fonctionne pas correctement. –

+0

Quel est le problème? Je l'ai testé avec les premier et deuxième échantillons de données et il renvoie un résultat correct pour les deux. Le seul problème est qu'il retourne la ligne de jour supplémentaire après le jour max. Mais il peut être filtré facilement. –

+0

Au lieu de MONTH (T1.date) - 1 = MOIS (T2. [Date]) il devrait être DATEDIFF (MOIS, T1.date, T2. [Date]) = -1 Mais j'aurais dû donner un autre exemple. Avec cette modification, cela fonctionne parfaitement. Thans! –