2016-07-20 6 views
4

Basic T-SQL Benutzer hier. Ich habe Probleme, eine Aufgabe zu erledigen, und würde mich über einige Hinweise freuen. Entschuldigung im Voraus für eventuelle Fehler, da Englisch nicht meine Muttersprache ist.Berechnung von Kundenreisen basierend auf Transaktionsdaten

Ich habe eine Tabelle mit vielen Transaktionen, der Einfachheit halber sagen wir, dass ich nur zwei Spalten habe: CUSTOMER_ID, das ist mein Kunde und DATE, welches das Datum der Transaktion ist.

Meine Kunden machen eine Menge Transaktionen, während sie in der Stadt sind, aber dann können sie Wochen, Monate oder sogar Jahre verbringen, bevor sie zurückkommen und wieder Transaktionen machen. Ich möchte irgendwie jede dieser "Reisen" identifizieren und die beteiligten Transaktionen gruppieren, dann möchte ich Thins wie Reisedauer berechnen, Anzahl der Transaktionen, usw.

Ich möchte eine Reise in Betracht ziehen wie jede neue Transaktion, die nach einer IDLE-Periode von 10 Tagen auftritt.

Lassen Sie mich versuchen, besser zu meiner Anfrage zu erklären, indem Sie einige einfache Beispiel mit:

Dies ist meine Transaktionen Tabelle:

+-------------+------------+ 
| CUSTOMER_ID | DATE | 
+-------------+------------+ 
| JHON  | 01-01-2016 | 
| JHON  | 01-02-2016 | 
| PEDRO  | 01-02-2016 | 
| JHON  | 01-05-2016 | 
| MIKE  | 01-05-2016 | 
| MIKE  | 01-10-2016 | 
| JHON  | 01-07-2016 | 
| …   | …   | 
| JHON  | 02-15-2016 | 
| JHON  | 02-18-2016 | 
| MIKE  | 02-19-2016 | 
| MIKE  | 02-19-2016 | 
+-------------+------------+ 

Bisher habe ich diese Abfrage gemacht, um die Besuche des Kunden aufzählen:

SELECT 
    CUSTOMER_ID, 
    DATE, 
    ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID ORDER BY DATE) as VISIT_NUM 

FROM 
    TRANSACTIONS 
WHERE 
    CUSTOMER_ID IN ('JHON','MIKE','PEDRO') 

die Abfrage laufen würde ein ähnliches Ergebnis wie diese geben:

+-------------+------------+-----------+ 
| CUSTOMER_ID | DATE | VISIT_NUM | 
+-------------+------------+-----------+ 
| JHON  | 01-01-2016 |   1 | 
| JHON  | 01-02-2016 |   2 | 
| JHON  | 01-07-2016 |   3 | 
| JHON  | 02-15-2016 |   4 | 
| JHON  | 02-18-2016 |   5 | 
| MIKE  | 01-05-2016 |   1 | 
| MIKE  | 01-10-2016 |   2 | 
| MIKE  | 02-19-2016 |   3 | 
| MIKE  | 02-19-2016 |   4 | 
| PEDRO  | 01-02-2016 |   1 | 
+-------------+------------+-----------+ 

Jetzt kommt der knifflige Teil: Ich muss irgendwie eine Abfrage erstellen, die (vielleicht die obige Abfrage als einen vorherigen Schritt verwendend) mir den Kunden mit ihnen Reise-Info zeigt, mit dem Beispiel fortsetzend würde das ideale Ergebnis folgendermaßen aussehen:

+-------------+----------+---------------+-------------+---------------+--------------+ 
| CUSTOMER_ID | TRIP_NUM | TRIP_START_DT | TRIP_END_DT | TRIP_DURATION | TRANSACTIONS | 
+-------------+----------+---------------+-------------+---------------+--------------+ 
| JHON  |  1 | 01-01-2016 | 01-07-2016 |    7 |   3 | 
| JHON  |  2 | 02-15-2016 | 02-18-2016 |    3 |   2 | 
| MIKE  |  1 | 01-05-2016 | 01-10-2016 |    5 |   2 | 
| MIKE  |  2 | 02-19-2016 | 02-19-2016 |    1 |   2 | 
| PEDRO  |  1 | 01-02-2016 | 01-02-2016 |    1 |   1 | 
+-------------+----------+---------------+-------------+---------------+--------------+ 

Wie Sie sehen können, kam Mr. Jhon 3 mal im Laufe des Monats Januar und kam im Februar wieder zurück. Da mehr als 10 Tage seit seiner letzten Transaktion im Januar verstrichen sind, möchte ich seine neuen Transaktionen als eine neue "Reise" für ihn betrachten. Mike hatte auch einige Aktivitäten im Januar und kam auch im Februar zurück, in seiner zweiten Reise machte er zwei Transaktionen am selben Tag, das würde ich auch gerne erklären. Wenn ein Kunde nur einen einzigen Tag hatte und etwas Aktivität hatte (wie im Fall von Herrn Pedro), würde ich diesen Eintages-Einzeltransaktions-Datensatz auch als einen Reisedatensatz betrachten.

Ich wäre sehr dankbar für jedes Licht auf diesem, ich habe ehrlich gesagt keine Ahnung, wie es weitergehen soll (ich habe über Cursor gelesen, aber es scheint wie dunkle Magie an diesem Punkt kann nicht einen Weg finden, sie auf diese zu implementieren).

Wir entschuldigen uns nochmals für grammatikalische Fehler und mögliche Auslassungen meinerseits. Ich würde alles weitere klären, wenn nötig.

+3

Ihr Englisch ist besser als 99% des englischen Muttersprachler. –

Antwort

1

Ich fand die perfekte Antwort woanders. Alles Gute geht an den Reddit User nvarscar für die tolle Lösung!

Ich werde kopieren seine/ihre Antwort nur unten, müssen sie für den Fall, jemand anderes in die Zukunft:

Sie eine Fensterfunktion Funktion verwenden können, die Sie Reihen zwischen aktuellen Zeile aggregieren hilft und alle vorhergehenden. Der Code sieht auch lang aus, aber zumindest werden Sie die Schritte sehen.

DECLARE @t TABLE 
    ([CUSTOMER_ID] varchar(5), [DATE] datetime) 
; 

INSERT INTO @t 
    ([CUSTOMER_ID], [DATE]) 
VALUES 
    ('JHON', '2016-01-01 00:00:00'), 
    ('JHON', '2016-01-02 00:00:00'), 
    ('PEDRO', '2016-01-02 00:00:00'), 
    ('JHON', '2016-01-05 00:00:00'), 
    ('MIKE', '2016-01-05 00:00:00'), 
    ('MIKE', '2016-01-10 00:00:00'), 
    ('JHON', '2016-01-07 00:00:00'), 
    ('JHON', '2016-02-15 00:00:00'), 
    ('JHON', '2016-02-18 00:00:00'), 
    ('MIKE', '2016-02-19 00:00:00'), 
    ('MIKE', '2016-02-19 00:00:00'), 
    ('JHON', '2016-02-01 00:00:00'), 
    ('JHON', '2016-02-02 00:00:00'), 
    ('PEDRO', '2016-03-02 00:00:00'), 
    ('JHON', '2016-03-05 00:00:00'), 
    ('MIKE', '2016-05-05 00:00:00'), 
    ('MIKE', '2016-05-10 00:00:00'), 
    ('JHON', '2016-03-07 00:00:00'), 
    ('JHON', '2016-04-15 00:00:00'), 
    ('JHON', '2016-04-18 00:00:00'), 
    ('MIKE', '2016-06-19 00:00:00'), 
    ('MIKE', '2016-06-19 00:00:00') 
; 


WITH CTE1 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, COUNT(*) AS Transactions 
FROM @t 
GROUP BY 
    [CUSTOMER_ID] 
, [DATE] 
) 
, CTE2 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, DATEDIFF(day,LAG([DATE]) OVER (PARTITION BY [CUSTOMER_ID] ORDER BY [DATE]),[DATE]) AS DaysSinceLastTransaction 
FROM CTE1 
) 
, CTE3 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, CASE WHEN DaysSinceLastTransaction > 10 THEN 1 ELSE 0 END AS TripTag --Here we set the idle tag 
FROM CTE2 
) 
, CTE4 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, SUM(TripTag) OVER (PARTITION BY [CUSTOMER_ID] ORDER BY [DATE] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS TripTag 
FROM CTE3 
) 
SELECT 
    [CUSTOMER_ID] 
, TripTag+1 AS TripNumber 
, MIN ([DATE]) AS TripStartDate 
, MAX ([DATE]) AS TripEndDate 
, DATEDIFF(day, MIN ([DATE]), MAX ([DATE])) AS TripDuration 
, SUM(Transactions) AS Transactions 
FROM CTE4 
GROUP BY [CUSTOMER_ID], TripTag 
2

Reisedauer Berechnung ist für alle Mitarbeiter in Ihrem Beispiel nicht Standard, so habe ich es gezwickt ersten Kunden-ID für alle

DEMO HERE

;with cte 
as 
(select cid,datee,datepart(month,datee) as monthh, 
    dense_rank() over (partition by cid order by datepart(month,datee)) as samemonth, 
count(0) over (partition by cid,datepart(month,datee)) as cnt 
from #temp 
) 
,cte1 as 
(
select cid,max(samemonth) as tripnumber,min(datee) as startdate,max(datee) as enddate, 
max(cnt) as numberoftrips 
from cte 
group by cid,samemonth 
) 
select *,datediff(day,startdate,dateadd(day,1,enddate))as duration 
from cte1 

Ausgabe folgen:

cid tripnumber startdate  enddate numberoftransactions duration 
JHON 1  2016-01-01 2016-01-07 3     7 
JHON 2  2016-02-15 2016-02-18 2     4 
MIKE 1  2016-01-05 2016-01-10 2     6 
MIKE 2  2016-02-19 2016-02-19 2     1 
PEDRO 1  2016-01-02 2016-01-02 1     1 
+1

Danke, dass du vier antwortest. War nicht genau das, was ich wollte, aber es hilft mir sehr! – JorgeDS

Verwandte Themen