2017-05-28 3 views
2

Ich versuche, ein biologisches "finde Kerngenom einer gegebenen Reihe von Organismen" Problem zu finden. Im Wesentlichen finden Sie bei einer Liste von Organismen alle Gene, die ihnen gemeinsam sind. Um die Biologie zu abstrahieren, können Sie sich vorstellen, alle Farben zu finden, die in einer Liste von Personen am beliebtesten sind (eine Person kann mehrere Lieblingsfarben haben).Selbst beitreten eine Tabelle n mal

Datenbanktabelle würde wie folgt aussehen:

name | fav_colour 
john | red 
john | blue 
john | green 
jason | red 
jason | blue 
matt | red 
matt | teal 

Der Benutzer kann eine Reihe von Namen angeben wie [john, jason], um aus [rot, blau] oder [John] to get [rot, blau, grün], oder [john, jason, matt] um [rot] zu bekommen.

Ich versuche, dies zu lösen, indem ich n Anzahl der Self Joins tun, wobei n die Anzahl der gelieferten Namen ist.

Gibt es eine Möglichkeit für mich, eine Anzahl von Self Joins von Tabellen zu tun, um dieses Problem für eine beliebige Anzahl von Namen zu lösen? Ich habe versucht, nach einer Möglichkeit zu suchen, dies über Postgres-Funktionen zu tun, kann aber die Anzahl n von Self Joins nicht herausfinden ... jede Hilfe oder Hinweise auf die richtige Richtung würden geschätzt werden.

Und nein, leider kann ich das Schema nicht ändern, um diese Art von Abfragen einfacher zu machen.

+1

Der Join-Ansatz ist nicht das, was zu mir spricht .... Mein erster Gedanke ist, entweder Aggregation zu verwenden, Zählen, wie viele Organismen haben jedes Gen mit Gruppe durch und count (*) und dann mit count = Anzahl von Organismen. Die andere Idee, die mir in den Sinn kommt, ist die Aneinanderreihung von Abfragen für jeden Organismus und die Verwendung von INTERSECT, um die gemeinsamen Elemente zu erhalten. – joshp

+0

* Genau wie * gibt ein Benutzer eine Reihe von Namen an? Können wir annehmen, dass sie sich in einer Tabelle mit einer Spalte befinden, Name? – philipxy

+0

@philipxy Ich habe auf eine gespeicherte Prozedur gehofft, die ein Array von Werten akzeptiert, die geparst und gezählt werden. Die Anzahl der Elemente im Array wäre n, was die Anzahl der erforderlichen Self-Joins wäre. – player87

Antwort

3

Ich glaube nicht, dass Sie dafür Self-Joins benötigen. Sie können die Aggregation und eine HAVING-Klausel verwenden:

with t(name, fav_colour) as (
     values ('john', 'red'), 
      ('john', 'blue'), 
      ('john', 'green'), 
      ('jason', 'red'), 
      ('jason', 'blue'), 
      ('matt', 'red'), 
      ('matt', 'teal') 
    ) 
select fav_colour 
from t 
where name in ('john', 'jason') 
group by fav_colour 
having count(*) = 2; 

Der Wert „2“ ist die Anzahl der Namen in der Liste. Das Ändern der IN Liste und der Anzahl sind die einzigen Änderungen, die Sie benötigen.

+0

Wie würde das funktionieren, wenn es auch andere Spalten gäbe? B. die Lieblingsfarbe basierend auf dem Wert in der Spalte fav_colour, aber auch das Alter (zwei verschiedene Altersgruppen im Fall von John, Jason) (wenn wir das Alter einer bestimmten Person angeben können, die ebenfalls funktioniert, dh die Gen-ID von a definierte Arten). Für meine Daten werden die gemeinsamen Gene basierend auf der Beschreibungsspalte gefunden, aber die Gene der verschiedenen Spezies haben unterschiedliche IDs, die für weitere Abfragen verwendet werden können. – player87

+2

@ player87. . . Wenn Sie eine andere Frage haben, fragen Sie sie als * eine andere Frage. Diese Frage bezieht sich speziell auf zwei Spalten und das Ändern der Frage könnte diese Antwort ungültig machen und Downvotes anziehen. Wenn Sie jedoch nur ein Alter aus den übereinstimmenden Zeilen möchten, können Sie 'array_agg()' verwenden. –

+0

Eigentlich funktioniert die array_agg() für was ich tun möchte.Aber nur ein Follow-up zu der ursprünglichen Frage, ist es tatsächlich möglich, Self-Join n-mal zu einer bestimmten Bedingung (d. H. Namensspalten sind einzigartig in den n Tabellen)? – player87