2016-03-28 17 views
1

2 sütun, birinci kimlik ve ikinci kimlikten oluşan bir PostgreSQL tablosum var. İçindeki her giriş, birinci ve ikinci kimlik arasında bir ilişki olduğu anlamına gelir ve ilk kimliğin her zaman ikinci kimlikten daha büyük olacağı garanti edilebilir.PostgreSQL'de optimal grafik ilişkisi oluşturma

Amacım, ağları (birbiriyle ilişkili çoklu kimlikler) algılayabilmesi için tabloyu işlemek ve bu ağların tablodaki tüm ilişkilerini değiştirmektir; böylece birinci kimlik, ağdaki büyük kimlikler ve İkinci kimlik her zaman ağdaki en küçük kimliktir.
Örnek:

D->C , C->B , B->A , F->E , H->G 

hale gelecek:

D->A , C->A , B->A , F->E , H->G 

Başka bir örnek:

D->C , D->B , D->A 

hale gelecek:

D->A , C->A , B->A 

bu kullanarak SQL veya Po nasıl yapılır prosedürel dil stgres?

Düzenleme: Kullandığım PostgreSQL sürümü 9.4. Tablo, her ikisi de birincil anahtar olarak sütun id1 (tamsayı) ve id2 (tamsayı) oluşur.

bu ikinci örnek kümesinde en küçük sonuçlandırmak için nasıl de (A, B, C), böyle bir tablo varsayıldığında küçük ID2

SELECT id1, MIN(id2) FROM table GROUP BY id1 
+0

İkinci örneğinizde: A'nın kümedeki en küçük (A, B, C) olduğu sonucuna nasıl ulaşırsınız? Lütfen her zaman Postgres sürümünüzü ve ideal olarak bir tablo tanımını sağlayın. –

cevap

1

belirlemek için bu sorgu kullanılır:

CREATE TABLE tbl (
    id1 int 
, id2 int 
, PRIMARY KEY (id1, id2) 
); 

Mantığınıza göre dairesel referanslar yapılamaz. Olmayan özyinelemeli vadede

WITH RECURSIVE cte AS (
    SELECT t1.id1, t1.id2, t2.id2 AS next_id2 
    FROM tbl t1 
    LEFT JOIN tbl t2 ON t2.id1 = t1.id2 

    UNION ALL 
    SELECT t1.id1, t1.next_id2, t2.id2 
    FROM cte t1 
    LEFT JOIN tbl t2 ON t2.id1 = t1.next_id2 
    WHERE t1.next_id2 IS NOT NULL -- stop iterating at end of graph 
    ) 
SELECT id1, id2 
FROM cte 
WHERE next_id2 IS NULL; -- only rows where the graph ends 

her satır seçin ve bir LEFT JOIN ile sonraki adımı bulmaya:

Bu recursive CTE işi yapardı.

Yinelemeli terimde, grafiğin sonuna ulaşana kadar ikinci kimliği bir sonraki adımla değiştirin (next_id2 IS NULL). Dış SELECT'da yalnızca grafiğin bittiği satırları döndür. Keyfi sıralama düzeninde sonuç.

Grafikler çatallanırsa en derin tavşan deliğini nasıl belirlediğiniz açık değil.

+0

Geç cevap için özür dilerim. PostgreSQL 9.4 kullanıyorum ve tablo için varsayım doğru. Daha önce hiç yinelemeli CTE kullanmamıştım (hala veritabanı için oldukça yeni: /), böylece ona bakacağım. Teşekkürler :) – Aldibe

+0

p.s: Evet, tabloda dairesel bir referans yoktur. Bulduğum olası sorunlar bu iki örnek ve muhtemelen bu ikisinin kombinasyonu. – Aldibe

+0

@Aldibe: Lütfen tüm tanımlayıcı bilgileri soruya koyun. Sorunuzun altındaki [düzenle] (http://stackoverflow.com/posts/36255607/edit) tuşuna basın.Ayrıca lütfen en önemli açıklama isteğime de hitap edin: “A'nın kümedeki en küçük (A, B, C)? –

İlgili konular