2016-11-10 4 views
0

versucht, nach der Antwort zu suchen, lesen Beiträge wie diese: SQL Self-join with data comparison for different days aber nicht in der Lage, ganz zu verstehen, wie dies in diesem Szenario funktionieren würde.ist es möglich, sich selbst zu verbinden, um nach anderen Daten zu fragen?

Würde mich über jede Hilfe freuen;

Ich habe eine Tabelle mit einem

  • UserID (Zahl)
  • Usertype (string, zeigt, wenn sie Mitglied oder Gast)

  • sales_date (Zeitstempel-Feld)

  • (plus andere Spalten wie das, was sie gekauft haben und die Kosten für Artikel, an denen ich momentan nicht interessiert bin)

Ich versuche eine Abfrage zu schreiben, die mir sagen wird, wie viele Leute pro Monat zwischen einem Mitglied und einem Gast waren. So kann ich Fragen beantworten wie "Wie viele Leute waren hier im September und kamen im Oktober zurück?" "Wie viele Leute waren Mitglieder im September, wurden aber im Oktober zu Gästen degradiert?" "Wie viele Leute waren Gäste im September, aber im Oktober wurden sie Mitglieder?"

1: Ist Self-Join der Weg zu gehen, wenn Sie für zwei verschiedene Zeiträume aus der gleichen Tabelle/derselben Abfrage fragen müssen?

2: Ich denke, ich muss für UserID, dann UserType für Sept vs UserType für Oktober fragen. Klingt das richtig? Nicht sicher, wie man nach 2 verschiedenen Daten fragt

SELECT 
     t1.UserID, 
     t1.UserType as UserTypeSept, 
     t2.UserType as UserTypeOct 
    FROM 
     my_table t1 
     join my_table t2 
      on t1.UserID = t2.UserID 
      AND t2.day > '2015-01-01' AND t2.day < '2015-02-01' 
    where 
     t1.day >'2015-02-01' AND t1.day <'2015-03-01' 
; 

Denke ich entlang der richtigen Spuren? Auch wenn dies funktioniert, wird es mir nicht sagen, wie viele von „Mitgliedern“ auf „Gäste“ von September bis Oktober geändert, aber zumindest zeigt ihre Werte in zwei verschiedenen Spalten

dank

+0

Welche DBMS verwenden Sie? –

+0

google bigquery – Bjorn

+0

Wichtig auf SO, können Sie akzeptierte Antwort markieren, indem Sie das Häkchen auf der linken Seite der veröffentlichten Antwort, unterhalb der Abstimmung. Siehe http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work#5235, warum dies wichtig ist. –

Antwort

0

ich empfehlen würde mit analytische Funktionen anstelle von Self Join, die teurer sind. Ihre Daten sind für Fensterdaten geeignet. Bitte führen Sie unter Abfrage und dann an Ihre Tabelle anpassen. Sie werden wahrscheinlich Format gedruckten Perioden benötigen und CASE-Klausel für Übergänge zwischen folgenden Monaten wie "Mitglied - Gast" zu aussagekräftigeren Namen verwenden.

 WITH 
    members AS ( 
    SELECT 1 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-01-01' AS sales_date 
    UNION ALL SELECT 1 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-02-01' AS sales_date 
    UNION ALL SELECT 2 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-01-01' AS sales_date 
    UNION ALL SELECT 2 AS UserID, 'Member' AS UserType,TIMESTAMP '2015-02-01' AS sales_date 
    UNION ALL SELECT 3 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-01-01' AS sales_date 
    UNION ALL SELECT 3 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-02-01' AS sales_date 
    UNION ALL SELECT 4 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-01-01' AS sales_date 
    UNION ALL SELECT 4 AS UserID, 'Member' AS UserType,TIMESTAMP '2015-02-01' AS sales_date 
    UNION ALL SELECT 5 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-07-01' AS sales_date 
    UNION ALL SELECT 5 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-08-01' AS sales_date 
    UNION ALL SELECT 6 AS UserID, 'Member' AS UserType,TIMESTAMP '2016-03-01' AS sales_date 
    UNION ALL SELECT 7 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-04-01' AS sales_date 
    UNION ALL SELECT 7 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-05-01' AS sales_date 
    UNION ALL SELECT 8 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-01-01' AS sales_date 
    UNION ALL SELECT 8 AS UserID, 'Member' AS UserType,TIMESTAMP '2016-02-01' AS sales_date 
    UNION ALL SELECT 9 AS UserID, 'Guest' AS UserType, TIMESTAMP '2016-01-03' AS sales_date 
    UNION ALL SELECT 9 AS UserID, 'Member' AS UserType,TIMESTAMP '2016-02-06' AS sales_date) 
SELECT 
    COUNT(*), 
    member, 
    period, 
    year 
FROM (
    SELECT 
    UserType, 
    UserID, 
    sales_date, 
    FORMAT_DATE("%Y",DATE(sales_date)) AS year, 
    CONCAT(
    FORMAT_DATE("%b",DATE(sales_date)), 
    ' - ', 
    FORMAT_DATE("%b", DATE(LEAD(sales_date,1) OVER (PARTITION BY userId ORDER BY sales_date ASC))) 
    ) AS period, 
    CONCAT(UserType,' - ', LEAD(UserType,1) OVER (PARTITION BY userId ORDER BY sales_date ASC)) AS member 
    FROM 
    members 
    ORDER BY 
    userid) 
WHERE 
    member IS NOT NULL 
    and year = '2016' 
GROUP BY 
year, 
    member, 
    period 
+0

Mann, das ist eine große Frage :) – Bjorn

+0

werde es heute versuchen, vielen Dank für die Zeit, um zu helfen. Diese Seite ist großartig! – Bjorn

+0

Gibt es einen Weg, um jeden Monat und nicht nur einen Tag zu machen? wo es sagt "TIMESTAMP '2015-02-01' AS sales_date)" könnte das etwas wie AND YEAR (sales_date) = '2015' UND MONTH (sales_date) = '2' Art von Sache sein? – Bjorn

0

1: Ist Selbst registrieren um den Weg zu gehen, wenn um 2 anderes Datum fragen aus derselben Tabelle/gleiche Abfrage reicht?

Nicht wirklich! Es kommt darauf an! In Ihrem Fall - siehe unten # 2

2: Ich denke ich für UserID fragen müssen, dann Usertype für September vs Usertype für

Oktober

Ich denke unten tut, was Sie erwarten.
Hinweis: Am Ende jedes Monats wird nach UserType gesucht und als Usertyp für den jeweiligen Monat verwendet.

/* 
WITH my_table AS (
    SELECT 1 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-09-01' AS sales_date UNION ALL 
    SELECT 1 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-09-02' AS sales_date UNION ALL 
    SELECT 1 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-09-03' AS sales_date UNION ALL 
    SELECT 1 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-09-10' AS sales_date UNION ALL 
    SELECT 1 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-10-01' AS sales_date UNION ALL 
    SELECT 1 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-10-02' AS sales_date UNION ALL 
    SELECT 2 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-09-01' AS sales_date UNION ALL 
    SELECT 2 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-10-01' AS sales_date UNION ALL 
    SELECT 3 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-09-01' AS sales_date UNION ALL 
    SELECT 3 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-10-01' AS sales_date UNION ALL 
    SELECT 4 AS UserID, 'Guest' AS UserType, TIMESTAMP '2015-09-01' AS sales_date UNION ALL 
    SELECT 4 AS UserID, 'Member' AS UserType, TIMESTAMP '2015-10-01' AS sales_date) 
*/ 
SELECT 
    UserID, 
    MAX(CASE WHEN sales_year_month = '2015-09' THEN UserTypeAtEndOfMonth END) AS UserTypeSept, 
    MAX(CASE WHEN sales_year_month = '2015-10' THEN UserTypeAtEndOfMonth END) AS UserTypeOct 
FROM (
    SELECT 
    UserID, 
    FORMAT_DATE('%Y-%m', DATE(sales_date)) AS sales_year_month, 
    ARRAY_AGG(UserType ORDER BY sales_date DESC LIMIT 1)[OFFSET(0)] AS UserTypeAtEndOfMonth 
    FROM my_table 
    GROUP BY 1, 2 
) 
GROUP BY 1 

Sie können Kommentare entfernen, wenn Sie es auf Beispieldaten testen möchten

+0

vielen dank, wirklich schätzen sie ihre zeit! – Bjorn

Verwandte Themen