2010-11-27 5 views
4

zählen Ich versuche, eine Abfrage zu schreiben, die die Anzahl der bidirektionalen (starken) Verbindungen zwischen Benutzern zählt, die Knoten im Diagramm darstellen.Wie die Anzahl der üblichen bidirektionalen Verbindungen in Grafik

die Abfrage Um zu testen, habe ich erstellt das folgende Beispiel

alt text

, die in der Tabelle monthly_connections_test gespeichert ist:

calling_party, called_party, link_strength 


z1 z2 1,0000000 
z1 z3 1,0000000 
z3 z1 1,0000000 
z1 z4 1,0000000 
z1 z5 1,0000000 
z5 z1 1,0000000 
z2 z4 1,0000000 
z2 z5 1,0000000 
z5 z2 1,0000000 
z2 z7 1,0000000 
z7 z2 1,0000000 
z4 z7 1,0000000 
z7 z4 1,0000000 
z2 z1 1,0000000 

Die folgende Abfrage gibt 2 für starke Verbindungen zwischen z1 und z2 anstelle von 1:

SELECT user1, user2, 0 AS calling_calling, 0 AS calling_called, 0 AS called_calling, 0 AS called_called, COUNT(*) AS both_directions 
FROM (SELECT monthly_connections_test.calling_party AS user1, monthly_connections_test_1.calling_party AS user2 
FROM   monthly_connections_test INNER JOIN 
         monthly_connections_test AS monthly_connections_test_1 ON 
         monthly_connections_test.called_party = monthly_connections_test_1.called_party AND 
         monthly_connections_test.calling_party < monthly_connections_test_1.calling_party) t1 
         INNER JOIN monthly_connections_test AS monthly_connections_test_2 ON 
         t1.user2 = monthly_connections_test_2.called_party 
         AND t1.user2 < monthly_connections_test_2.calling_party 
GROUP BY t1.user1, t1.user2 

Die Beispiele werden folgende Ergebnisse erzielt:

z1 z2 0 0 0 0 2 
z2 z3 0 0 0 0 3 
z2 z4 0 0 0 0 1 
z1 z5 0 0 0 0 3 
z2 z5 0 0 0 0 3 
z3 z5 0 0 0 0 2 
z1 z7 0 0 0 0 4 
z2 z7 0 0 0 0 1 
z5 z7 0 0 0 0 1 

Wer weiß, wie die Abfrage ändern, um die Anzahl der gemeinsamen Nachbarn zurückkehren, die in beiden Richtungen verbunden sind (in diesem Beispiel den richtigen Wert für z1, z2 1 als z5 ist in beiden Richtungen mit z1 und z2 verbunden)?

Das Problem ist, dass ich in dem Teil erraten

INNER JOIN monthly_connections_test AS monthly_connections_test_2 ON 
         t1.user2 = monthly_connections_test_2.called_party 
         AND t1.user2 < monthly_connections_test_2.calling_party 

Das richtige Ergebnis folgendes sein sollte: in einer solchen Art und Weise formuliert werden, hat

z1 z2 0 0 0 0 1 
z2 z3 0 0 0 0 1 
z2 z4 0 0 0 0 1 
z1 z5 0 0 0 0 1 
z2 z5 0 0 0 0 1 
z3 z5 0 0 0 0 1 
z1 z7 0 0 0 0 1 
z2 z7 0 0 0 0 0 
z5 z7 0 0 0 0 1 

Die Join-Bedingung, dass jede Verbindung gezählt nur einmal (bisher eingeschlossene Verbindungen müssen an dieser Stelle ausgeschlossen werden), haben aber die Lösung nicht herausgefunden.

P.S. Da die Originaltabelle aus 24M-Datensätzen besteht, muss die Abfrage so geschrieben werden, dass sie die Ergebnisse in dem akzeptablen Zeitraum zurückgibt. Beim Versuch, die Abfrage mit mehreren Auswahlmöglichkeiten zu schreiben, dauerte es zunächst zu lange, bis sie ausgeführt wurde.

+0

Wenn Sie ein Beispiel für ein richtiges Eingabe-Ausgabe-Paar angeben, wäre es für mich und andere Benutzer leichter zu verstehen, was ne ist getan werden. Im Moment verstehe ich, dass du die bidirektionalen Links zählen willst, aber die Abfrage dafür ist einfach, viel einfacher als das, was du geschrieben hast, also denke ich jetzt, dass ich etwas falsch gemacht habe. – AlexanderMP

Antwort

0

Durch mehrere Lösungen die folgende Abfrage die richtigen Ergebnisse für das Beispiel oben zurück versuchen:

SELECT t1.user1, t1.user2, 0 AS calling_calling, 0 AS calling_called, 0 AS called_calling, 0 AS called_called, COUNT(*) AS both_directions 
FROM (SELECT monthly_connections_test.calling_party AS user1, monthly_connections_test_1.calling_party AS user2, monthly_connections_test.called_party AS calledUser 
FROM   monthly_connections_test INNER JOIN 
         monthly_connections_test AS monthly_connections_test_1 ON 
         monthly_connections_test.called_party = monthly_connections_test_1.called_party AND 
         monthly_connections_test.calling_party < monthly_connections_test_1.calling_party) t1 
         INNER JOIN monthly_connections_test AS monthly_connections_test_2 ON 
         monthly_connections_test_2.called_party = t1.user1 
         AND monthly_connections_test_2.calling_party = t1.calledUser 
0

schreiben zuerst eine Tabellenwertfunktion -

create function getBiConnectedNeighbours 
(
@P_PARTY nvarchar(50) 
) 
returns table 
as 
return 
(
    select called_party as neighbour 
    from monthly_connections_test a 
    where calling_party = @P_PARTY 
     and exists (select 1 from monthly_connections_test b 
         where a.called_party = b.calling_party and 
          b.called_party = a.calling_party) -- this subquery is to get bidirectionals only 

) 

dann die Funktion als

verwenden
select count(1) 
from getBiConnectedNeighbours('z1') a inner join 
    getBiConnectedNeighbours('z2') b on a.neighbour = b.neighbour 
+0

dies funktioniert in SQL-Server .. nicht wissen, welche Db Sie verwenden, aber ändern Sie die Syntax entsprechend, wenn erforderlich. –