2016-04-26 2 views
0

Ich habe eine Postgresql-Datenbank (technisch Greenplum) mit Daten über Einzelpersonen im Laufe der Zeit. Die Datenbank hat drei Felder: user_id, monthly_date und account_value. Wenn ich eine Abfrage einfüge, muss ich die Ergebnisse von einem Remote-Server herunterladen, so dass die Bandbreite ein Problem darstellt. Da das Feld user_id eine sehr lange Zeichenfolge (etwa 50 Zeichen) ist, möchte ich einen Zahlenwert zurückgeben, der 1: 1 mit jedem Wert von user_id entspricht, da dies weniger Speicherplatz benötigt.Wie kann ich einen langen String-Identifier in einer einzigen Abfrage (aus Gründen der Bandbreite) eindeutig einem numerischen Wert zuordnen?

Zum Beispiel könnte die Datenbank Beispieldaten wie diese:

63a9364385350b13473279 Jan-2000 
63a9364385350b13473279 Feb-2000 
2066937e2887w206010393 Apr-2001 
036686037e507d01764237 Mar-2003 
036686037e507d01764237 Jun-2003 
036686037e507d01764237 Jul-2003 
036686037e507d01764237 Dec-2003 
90829x098327549n286418 Apr-2004 
90829x098327549n286418 Sep-2004 
67518x834512306933u500 Nov-2000 

und ich versuche, eine Abfrage zu arbeiten ROW_NUMBER() und verschiedene Fensterfunktionen wie PARTITION BY Ergebnisse wie folgt zu erhalten:

1 Jan-2000 
1 Feb-2000 
2 Apr-2001 
3 Mar-2003 
3 Jun-2003 
3 Jul-2003 
3 Dec-2003 
4 Apr-2004 
4 Sep-2004 
5 Nov-2000 

Ich weiß, das sind keine tatsächlichen Datenbankformate, aber ich verwende sie nur als Beispieldaten. Ist das möglich? Es ist mir egal (obwohl es nett und sehr nett zu sehen wäre), wenn zum Beispiel 63a9364385350b13473279 auf 1 in einer Abfrage und 2 in der nächsten, aber in jeder beliebigen Abfrage, 63a9364385350b13473279 sollte immer auf den gleichen Wert unabhängig zuordnen des Datums. Die abgebildeten Zahlen müssen nicht der Reihe nach sein oder irgendeinen bedeutungsvollen Wert neben der Einzigartigkeit haben.

+0

Haben Sie sich mit dem 'serial' -Typ von gp angesehen, um einen automatisch generierten Integerschlüssel für Ihre Benutzer zu haben? – jmelesky

+0

@jmelesky Ich kontrolliere das Schema überhaupt nicht. Die Datasets werden wie von einem Drittanbieter erworben und in ein Data Warehouse an einem anderen Ort hochgeladen, und wenn ich Daten aus der Datenbank haben möchte, kann ich nur eine Abfrage in ein Webformular eingeben. Wenn es fertig ist, erhalte ich einen Link zum Download per E-Mail. Leider funktioniert das System meines Unternehmens und ich kann es nicht ändern. –

+0

@jmelesky Also, um klar zu sein, sogar die Datenbankadministratoren meiner Firma kontrollieren das Schema in diesem Sinne nicht wirklich. Der Datenanbieter von Drittanbietern verkauft uns die Daten in diesem Format, und wir können es entweder übernehmen oder verlassen (und leider können wir es nicht verlassen, da es der einzige Anbieter ist, der diese Daten verkauft). –

Antwort

1

Wenn Sie nur eine eindeutige Nummer benötigen, wird dies den Trick:

SELECT 
     id, 
     split_part(t.d, '-', 2), 
     row_number() OVER all_window - row_number() OVER group_window AS a_unique_number_by_id 
FROM (
VALUES 
     ('63a9364385350b13473279','Jan-2000'), 
     ('63a9364385350b13473279','Feb-2000'), 
     ('2066937e2887w206010393','Apr-2001'), 
     ('036686037e507d01764237','Mar-2003'), 
     ('036686037e507d01764237','Jun-2003'), 
     ('036686037e507d01764237','Jul-2003'), 
     ('036686037e507d01764237','Dec-2003'), 
     ('90829x098327549n286418','Apr-2004'), 
     ('90829x098327549n286418','Sep-2004'), 
     ('67518x834512306933u500','Nov-2000') 
) as t(id, d) 
WINDOW group_window AS (
     PARTITION BY id 
     ORDER BY split_part(t.d, '-', 2) 
), all_window AS (
     ORDER BY split_part(t.d, '-', 2) 
); 

Hier ist das Ergebnis:

  id   | split_part | a_unique_number_by_id 
------------------------+------------+----------------------- 
63a9364385350b13473279 | 2000  |      0 
63a9364385350b13473279 | 2000  |      0 
67518x834512306933u500 | 2000  |      2 
2066937e2887w206010393 | 2001  |      3 
036686037e507d01764237 | 2003  |      4 
036686037e507d01764237 | 2003  |      4 
036686037e507d01764237 | 2003  |      4 
036686037e507d01764237 | 2003  |      4 
90829x098327549n286418 | 2004  |      8 
90829x098327549n286418 | 2004  |      8 
(10 rows) 

Sie sollten es mit einer anderen Spalte erneut um das Original zu halten Bestellung.

-1

Versuchen Sie, die unten Skript

create table test_schema.source_data (id varchar(50), dt varchar(50)); 

insert into test_schema.source_data 
values ('63a9364385350b13473279','Jan-2000'), 
    ('63a9364385350b13473279','Feb-2000'), 
    ('2066937e2887w206010393','Apr-2001'), 
    ('036686037e507d01764237','Mar-2003'), 
    ('036686037e507d01764237','Jun-2003'), 
    ('036686037e507d01764237','Jul-2003'), 
    ('036686037e507d01764237','Dec-2003'), 
    ('90829x098327549n286418','Apr-2004'), 
    ('90829x098327549n286418','Sep-2004'), 
    ('67518x834512306933u500','Nov-2000'); 


create temporary table id_mapping 
as 
select t1.id, row_number() over(order by t1.id) rownum 
from (
SELECT distinct id 
FROM test_schema.source_data 
) t1; 

select t1.id, t1.dt, t2.rownum 
from 
test_schema.source_data t1 
join id_mapping t2 
on t1.id = t2.id; 

Und hier ist das Ergebnis

id      dt   rownum 
------------------------+------------+----- 
036686037e507d01764237 Dec-2003 1 
036686037e507d01764237 Jul-2003 1 
036686037e507d01764237 Jun-2003 1 
036686037e507d01764237 Mar-2003 1 
2066937e2887w206010393 Apr-2001 2 
63a9364385350b13473279 Feb-2000 3 
63a9364385350b13473279 Jan-2000 3 
67518x834512306933u500 Nov-2000 4 
90829x098327549n286418 Sep-2004 5 
90829x098327549n286418 Apr-2004 5 
+0

Dies ist wahrscheinlich eine anständige Möglichkeit, dies zu tun, aber leider kann ich nur eine Abfrage zu einem Zeitpunkt (kein Skript) und die Schnittstelle speichert Tabellen zwischen Abfragen nicht, so dass die'Auswahl 'Anweisung keinen Zugriff haben zu der temporären Tabelle, die in der vorherigen Anweisung erstellt wurde. –

1

Ich glaube, Sie suchen nach DENSE_RANK().

create table sample_data 
(userid varchar(50) not null, 
monthly_date date not null) 
distributed by (userid); 

insert into sample_data (userid, monthly_date) values 
('63a9364385350b13473279','2000-01-01'), 
('63a9364385350b13473279','2000-02-01'), 
('2066937e2887w206010393','2001-04-01'), 
('036686037e507d01764237','2003-03-01'), 
('036686037e507d01764237','2003-06-01'), 
('036686037e507d01764237','2003-07-01'), 
('036686037e507d01764237','2003-12-01'), 
('90829x098327549n286418','2004-04-01'), 
('90829x098327549n286418','2004-09-01'), 
('67518x834512306933u500','2000-11-01'); 

select dense_rank() over(order by userid) as new_userid, userid, monthly_date 
from sample_data 
order by 2; 

new_userid |   userid   | monthly_date 
------------+------------------------+-------------- 
     1  | 036686037e507d01764237 | 2003-06-01 
     1  | 036686037e507d01764237 | 2003-07-01 
     1  | 036686037e507d01764237 | 2003-12-01 
     1  | 036686037e507d01764237 | 2003-03-01 
     2  | 2066937e2887w206010393 | 2001-04-01 
     3  | 63a9364385350b13473279 | 2000-02-01 
     3  | 63a9364385350b13473279 | 2000-01-01 
     4  | 67518x834512306933u500 | 2000-11-01 
     5  | 90829x098327549n286418 | 2004-09-01 
     5  | 90829x098327549n286418 | 2004-04-01 
(10 rows) 
Verwandte Themen