2017-02-09 2 views
-1

SITUATIONPostgreSQL - Wählen Sie nur 1 Zeile für jede ID

ich auf einer Reise Engine Website arbeite und bin eine komplexe Abfrage zu schreiben Besucher die Suchanfragen mit ihren Buchungen basierend auf IP-Adresse, entsprechen Ziel und Datum so kann ich das Umrechnungsverhältnis später ausarbeiten.

PROBLEM

Es braucht mehrere -Umwandlungsverhältnisse auf einem Parameter basiert sein (in diesem Fall die utm_source, die ich von einem RequestUrl extrahieren in der Suchtabelle gespeichert). Das Problem ist, einige Benutzer machen mehrere Suchen von verschiedenen Standorten .. manchmal bekommen wir die utm_source in der Anfrage und manchmal nicht ... und natürlich müssen wir zu nur 1 Buchung übereinstimmen. Screenshot von Abfrageergebnis unten besser zu verstehen:

enter image description here

Siehe die 3. und 4. Reihen die gleiche Buchung ID haben, etc .. aber unterschiedliche Werte für die Wert Spalte. Ich muss nur eine davon auswählen, aber nicht beide. Grundsätzlich, wenn es mehr als 1 gibt, muss ich die 1 wählen, die nicht "N/A" ist.

MY QUERY:

SELECT DISTINCT "B"."Id" AS "BookingId", "PQ"."IPAddress", "PQ"."To", "PQ"."SearchDate", "PQ"."Value" 
FROM 
(
    SELECT DISTINCT "IPAddress", "To", "CreatedAt"::date AS "SearchDate", COALESCE(SUBSTRING("RequestUrl", 'utm_source=([^&]*)'), 'N/A') AS "Value" 
    FROM dbo."PackageQueries" 
    WHERE "SiteId" = '<The ID>' 
    AND "CreatedAt" >= '<Start Date>' 
    AND "CreatedAt" < '<End Date>' 
) AS "PQ" 
INNER JOIN dbo."Bookings" AS "B" 
    ON "PQ"."IPAddress" = "B"."IPAddress" 
    AND "B"."To" = "PQ"."To" 
    AND "B"."BookingDate"::date = "PQ"."SearchDate" 
WHERE "B"."SiteId" = '<The ID>' 
AND "B"."BookingStatus" = 2 
AND "B"."BookingDate" >= '<Start Date>' 
AND "B"."BookingDate" < '<End Date>' 
ORDER BY "B"."Id", "PQ"."IPAddress", "PQ"."To"; 
+1

http://stackoverflow.com/questions/tagged/postgresql+greatest-n-per-group –

+0

@a_horse_with_no_name, Danke für den Link .. und nicht so sehr für den downvote . :-D. Dies ist eine etwas komplexere Situation als diese. Zum einen kann ich nicht einfach nach irgendeinem sofort verfügbaren Integer- oder Datum/Zeit-Wert sortieren und als solches denke ich nicht, dass es einer Down-Abstimmung würdig wäre ... aber so sei es. Ich habe eine Lösung gefunden, und ich werde meine eigene Antwort in einem Moment veröffentlichen ... – Matt

+0

Ich habe nicht –

Antwort

0

ich eine Lösung gefunden und basiert sie auf das, was ich hier gefunden: Return rows that are max of one column in Postgresql und hier: Postgres CASE in ORDER BY using an alias

Meine Lösung ist wie folgt:

SELECT "BookingId", "IPAddress", "To", "SearchDate", "Value" 
FROM 
(
    SELECT DISTINCT 
     "B"."Id" AS "BookingId", 
     "PQ"."IPAddress", 
     "PQ"."To", 
     "PQ"."SearchDate", 
     "PQ"."Value", 
     RANK() OVER 
     (
      PARTITION BY "B"."Id" 
      ORDER BY 
      CASE 
       WHEN "PQ"."Value" = 'N/A' THEN 1 
       ELSE 0 
      END 
     ) AS "RowNumber" 
    FROM 
    (
     SELECT DISTINCT "IPAddress", "To", "CreatedAt"::date AS "SearchDate", COALESCE(SUBSTRING("RequestUrl", 'utm_source=([^&]*)'), 'N/A') AS "Value" 
     FROM dbo."PackageQueries" 
     WHERE "SiteId" = '<Site ID>' 
     AND "CreatedAt" >= '<Start Date>' 
     AND "CreatedAt" < '<End Date>' 
    ) AS "PQ" 
    INNER JOIN dbo."Bookings" AS "B" 
     ON "PQ"."IPAddress" = "B"."IPAddress" 
     AND "B"."To" = "PQ"."To" 
     AND "B"."BookingDate"::date = "PQ"."SearchDate" 
    WHERE "B"."SiteId" = '<Site ID>' 
    AND "B"."BookingStatus" = 2 
    AND "B"."BookingDate" >= '<Start Date>' 
    AND "B"."BookingDate" < '<End Date>' 
) T 
WHERE "RowNumber" = 1 
ORDER BY "BookingId", "IPAddress", "To"; 

Etwas langatmig, aber es macht den Trick gut. Ich hoffe, es hilft anderen.

EDIT

Das war nicht das Ende der Geschichte: dort, in dem noch einige Fälle waren war ich mehr als 1 Wert bekommen. Die Antwort war, die CASE-Anweisung zu ändern, um eine eindeutige Zahl für jeden Textwert zu generieren. Die Lösung ist hier zu finden: PostgreSQL - Assign integer value to string in case statement

Verwandte Themen