2016-06-01 15 views
1

Ich habe eine Tabelle mit 50k Zeilen, die Spalte A (BIGINT, Beispiel Kundenkonto ID) und Spalte B (Datum, Beispiel - letzte Kaufdatum) hat.Berechne Perzentile basierend auf Daten in SQL

Ich würde gerne verstehen, wie% der Kunden ihren letzten Kauf in der Top 25% Kachel, Top 50% Kachel, 75% Kachel des angegebenen Datumsbereichs gemacht haben, also kann ich basierend auf all diesen Kundenkonto IDs sagen wo Die meisten unserer letzten Einkäufe sind verzerrt. Irgendwelche Gedanken darüber, wie man in sql erreicht?

Tabelle: alltransations

ACCT_ID   | DATE 
----------------|--------------- 
23748234782947 | 05-15-2016 
28178792839838 | 05-01-2016 
28178092734538 | 02-12-2016 
28347732839867 | 01-15-2016 
28170909362959 | 10-10-2015 
28171334099090 | 11-11-2015 
28109129330023 | 12-25-2014 
28172377859289 | 10-31-2014 

Antwort

0

Ich bin nicht sicher, ob ich Sie richtig mit den Fliesen erhalten, aber wenn man die Timerange in vier Regionen bedeuten, indem man würde es so für ein Intervall von 2016- arbeiten 02-01 bis 2016-06-01. Kompromiss: manuelle Berechnung der Intervalle; möglich, eine dieses durch Datumsberechnungen tun kann, zu

CREATE TABLE tblA (ACCT_ID INTEGER, PDATE DATE); 

INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1000,'2016-05-21'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1001,'2016-05-11'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1002,'2016-05-24'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1003,'2016-04-21'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1004,'2016-02-12'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1005,'2016-02-21'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1001,'2016-03-22'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1002,'2016-04-01'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1005,'2016-04-01'); 
INSERT INTO TblA(ACCT_ID, PDATE) VALUES (1006,'2016-04-01'); 

    SELECT DISTR.DATE_RANGE, COUNT(DISTR.ACCT_ID)/OVRL.TOTALCNT 
FROM (SELECT 'TOP25' as DATE_RANGE, A.ACCT_ID 
     FROM tblA A 
     WHERE A.PDATE BETWEEN STR_TO_DATE('01.05.2016', '%m/%d/%Y') AND STR_TO_DATE('01.06.2016', '%m/%d/%Y') 
     UNION ALL 
     SELECT 'TOP50' as DATE_RANGE, B.ACCT_ID 
     FROM tblA B 
     WHERE B.PDATE BETWEEN STR_TO_DATE('01.04.2016', '%m/%d/%Y') AND STR_TO_DATE('01.06.2016', '%m/%d/%Y') 
     UNION ALL 
     SELECT 'TOP75' as DATE_RANGE, C.ACCT_ID 
     FROM tblA C 
     WHERE C.PDATE BETWEEN STR_TO_DATE('01.03.2016', '%m/%d/%Y') AND STR_TO_DATE('01.06.2016', '%m/%d/%Y') 
     UNION ALL 
     SELECT 'ALL' as DATE_RANGE, C.ACCT_ID 
     FROM tblA C 
     WHERE C.PDATE BETWEEN STR_TO_DATE('01.02.2016', '%m/%d/%Y') AND STR_TO_DATE('01.06.2016', '%m/%d/%Y')) DISTR 
, (SELECT COUNT(*) AS TOTALCNT FROM tblA A WHERE A.PDATE BETWEEN STR_TO_DATE('01.03.2016', '%m/%d/%Y') AND STR_TO_DATE('01.06.2016', '%m/%d/%Y')) OVRL 
GROUP BY DISTR.DATE_RANGE, OVRL.TOTALCNT 

ALL 10 10 
TOP25 3 10 
TOP50 7 10 
TOP75 8 10 
0

Diese Lösung liefern wird dynamisch Datum Quartile basierend auf dem gesamten Datumsbereich Ihres Datensatz, dann zeigt den Prozentsatz des IDs erstellen dass trat in der Quartile:

select unix_timestamp(min(date)) into @start from p; 
select unix_timestamp(max(date)) into @end from p; 
Set @25 = 0.25 *(@end - @start)[email protected]; 
Set @50 = 0.50 *(@end - @start)[email protected]; 
Set @75 = 0.75 *(@end - @start)[email protected]; 

SELECT 
CASE WHEN unix_timestamp(date)>@75 then 4 
WHEN unix_timestamp(date)>@50 then 3 
WHEN unix_timestamp(date)>@25 then 2 
ELSE 1 END as Quartile, 
round(count(id)/(select count(*) from p)*100,2) as Percentage 
FROM p 
GROUP BY Quartile; 

Here is a functional example mit etwas mehr Detail und Formatierung.

Wenn Sie die Hälfte Ihrer Daten am Anfang und halb am Ende haben, werden Q1 und Q4 nur dynamisch angezeigt.

Zuerst Variablen als Bereich festlegen und dann für jede Quartil- oder andere Zeitsegmentpartition aufteilen.

Die CASE Anweisung kaskadiert von großen zu kleinen Daten, alle in UNIX_TIMESTAMP Format für leichtere Arithmetik, von Quartile zu Quartile übergeben, wie es fehlschlägt.

Dieselbe Struktur kann verwendet werden, um Datumsbereiche nach Segmenten, n-Kacheln, aufzuteilen.