2016-08-22 11 views
1

Um die Effektivität des Gebens eines kostenlosen Produkts bei der Erlangung neuer Kunden zu messen, möchte ich die Anzahl der Kunden finden, die für eine Bestellung bezahlt haben, nachdem sie nur eine kostenlose Bestellung erhalten haben. Meine Tabelle wie folgt aussieht:Suchen von Zeilen mit bestimmten Bedingungen nach Reihen anderer Bedingungen

id | user | total 
----------------- 
1 1  0.00 
2 1  57.33 
3 2  58.21 
4 2  0.00 
5 3  26.10 
6 3  0.00 
7 3  64.94 
8 4  0.00 
9 5  34.54 

In dieser Tabelle gibt es fünf Kunden: 1, 2, 3, 4 und 5. Dies gilt für alle denkbaren Bedingungen.

  • Benutzer 1 eine kostenlose Bestellung erhalten und dann einen bezahlten Auftrag, zählt diese
  • Benutzer 2 einen bezahlten Auftrag platziert und erhielten dann eine freie Ordnung, das ist nicht
  • User 3 zählt eine bezahlte Bestellung , dann einen freien Auftrag erhielt, legte dann einen bezahlten Auftrag, dies nicht
  • Benutzer 4 erhielt eine kostenlose Bestellung zählt, ist dies nicht
  • Benutzer 5 einen bezahlten Auftrag zählt platziert, dies nicht
zählt

Sie können sehen, dass ich mich nur um Benutzer kümmere, die keine bezahlte Bestellung aufgegeben haben, bevor sie eine kostenlose Bestellung erhalten haben, und dann eine bezahlte Bestellung aufgegeben haben. Eine deklarative Definition des Grafen ich suche ist:

  • Benutzer einen Auftrag vergaben n wo n->total > 0 nach Auftrag empfangen m, wo m->total == 0 und m->id < n->id. Es gibt keine Bestellung w wo w->total > 0 und w->id < m->id.

Einige create table Code:

create table orders (
    id int NOT NULL AUTO_INCREMENT, 
    user int, 
    total decimal(6,2), 
    PRIMARY KEY(id) 
); 

insert into orders (user, total) values 
    (1, 0.00), 
    (1, 57.33), 
    (2, 58.21), 
    (2, 0.00), 
    (3, 26.10), 
    (3, 0.00), 
    (3, 64.94), 
    (4, 0.00), 
    (5, 34.54); 

Die erwartete Ausgabe in diesem Fall würde 1 sein.

+0

ist diese Zeile korrekt? ** Sie können sehen, dass ich mich nur um Benutzer kümmere, die keine bezahlte Bestellung aufgegeben haben, bevor Sie eine bezahlte Bestellung erhalten haben. ** – 1000111

+0

Um Ihrer Logik zu entsprechen, müssen wir uns die drei neuesten ID - Werte für jeden Benutzer und die entsprechende Zeitstempel. Dies ist in MySQL ein wenig schwierig, und ich denke, die Antwort könnte dynamisches SQL erfordern. –

+0

@ 1000111 Entschuldigung, habe einen Tippfehler gemacht. Ich habe es behoben, es hätte sein sollen "wer hat keine bezahlte Bestellung aufgegeben, bevor er eine kostenlose Bestellung erhalten hat". – gator

Antwort

2

Einfache Aggregation kombiniert Mit der bedingten Aggregation erhalten Sie den Benutzer, den Sie suchen.

SELECT 
    [user] 
    ,MIN(id) as MinId 
    ,MIN(CASE WHEN total = 0 THEN id END) as MinZeroId 
    ,MIN(CASE WHEN total > 0 THEN id END) as MinPositiveId 
FROM 
    orders 
GROUP BY 
    [user] 
HAVING 
    MIN(id) = MIN(CASE WHEN total = 0 THEN id END) 
    AND MIN(CASE WHEN total > 0 THEN id END) > MIN(CASE WHEN total = 0 THEN id END) 

, dass die minimale ID für den Benutzer gegen den Mindest-ID für $ 0 Gesamt vergleicht und vergleicht dann den Mindest-ID für eine Gesamt> $ 0 auf die Minimum-ID für $ 0 Gesamtsumme.

Und wenn Sie die ursprünglichen Datensätze möchten, fügen Sie einfach eine äußere Auswahl hinzu, um zu ihr zu gelangen.

SELECT o.* 
FROM 
    (
     SELECT 
      [user] 
     FROM 
      orders 
     GROUP BY 
      [user] 
     HAVING 
      MIN(id) = MIN(CASE WHEN total = 0 THEN id END) 
      AND MIN(CASE WHEN total > 0 THEN id END) > MIN(CASE WHEN total = 0 THEN id END) 
    ) t 
    INNER JOIN orders o 
    ON t.[user] = o.[user] 
0

Sie möchten die Datensatzpaare (self join), wobei der erste Datensatz (die WHERE-Klausel) eine Nullsumme hat und es einen nachfolgenden Datensatz mit einer Gesamtmenge ungleich null gibt. (Muss nicht der nächste Datensatz, nicht wahr?)

Select i.User, i.total firstTotal, 
    n.Total firstpaidTotal 
from table i 
    join table n 
    on n.Id > i.id 
     and n.user = i.user 
     and n.total > 0 
where i.total = 0 
    and not exists 
    (Select * from table 
    where user = i.user 
     and id < i.Id)   
+0

Nicht gerade wegen Benutzer 3 in seinem Beispiel. Wenn 0.00 dann> 0.00 dann 0.00 sollte es ausgeschlossen werden, was bei Ihrer Abfrage nicht der Fall wäre. Netter Anfang sowieso :-) –

+0

Das nicht existierte würde Benutzer 3 ausschließen. Es erlaubt nur Aufzeichnungen, in denen die Identifikation die niedrigste für diesen Benutzer ist und das Gesamt = 0 –

0

Dies könnte Ihre Frage lösen:

select a.id from orders a 
join orders b on (a.user = b.user and a.id < b.id and a.total = 0) 
join (select min(id) as id, user from orders group by user) c on (a.user = c.user and a.id = c.id) 

Lassen Sie mich wissen, wenn etwas falsch ist :)

0

Noch eine andere mögliche Lösung, obwohl ich persönlich mag @ Matt Antwort auf diese:

SELECT a.user 
FROM orders a 
    -- search first user_line 
    JOIN (
     SELECT b.user, MIN(b.id) first_id 
     FROM orders b 
     GROUP BY b.user 
    ) c ON a.user = c.user AND a.id = c.first_id 
WHERE 
    -- check first line is total=0 
    a.total = 0 
    -- has later lines with total>0 
    AND EXISTS (
     SELECT 'exists' 
     FROM orders c 
     WHERE 
     c.user = a.user 
     AND c.total > 0 
     AND c.id > a.id 
    ) 
Verwandte Themen