Bir SQL Query backwords anne saymak?

8 Cevap php

Ben (Wordpress tarafından oluşturulan) bir MySQL veritabanı var ve bu ne gibi görünüyor benzer:

ID    pvardırntID     otherStuff
54    55           this is a test
55    56           another test
56    0            last test

Ne yapmam gereken bir sayfası ne kadar derin aşağı kontrol etmektir. Ben pvardırntId 0 ulaştığında bitmiş olduğunu biliyorum.

Ben 3 querys yazabilirsiniz ve ardından 0'a eşit olduğunda kontrol, ama sadece 1 sorgu ile mümkün eğer daha güzel olurdu. Bu mümkün mü? Nasıl?

Here is an example:

  • ID: 56 veli 0 vardır ve DERİNLİĞİNİ 0 vardır (1 şimdi sorgu).
  • ID: 55 sonra ebeveyni 56 0 vardır ve DERİNLİĞİNİ 1 var (şimdi 2 querys).
  • ID: 54 sonra 56 sonra 0 ebeveyni 55 sahiptir ve derinlik var 2 (şimdi 3 querys).

Ben "yanlış yol" (bir sorgu, her bir derinlik seviyesi ile) çözmüş burada get_depth()

Sorun, bir özyinelemeli fonksiyon bulunuyor ve her derinliği bir daha sorgu gerektirir.

8 Cevap

Hatta SQL olmadan, bunu çözmek için çok kolay bir yol buldu. Benim durumumda Wordpress birçok etiket ve sınıfları hangi kullanıyorum.

<?php $depth = count($post->ancestors); echo $depth; ?>

Basit ama işe yarıyor.

Çalıştıkları bu sorun üzerinde çözüm, sadece Wordpress daha fazla çalışır. Ben doğru biri olarak benim çözüm ayarlamanız gerekir, sen ne düşünüyorsun?

Bir ilişkisel veritabanı bir ağacı sorgulamak istiyorsanız, ilişkilerini göstermek için nested set kullanın. Bu, bir öğenin derinliğini, atalarının tam listesini, ilgili tüm durumlarda bulmak, ve çok daha fazlası bulmak için tek bir sorgu kullanmak izin verir.

Sen bir sayacı artırır ve yerine tek bir sorguda bu gerçekleştirmek için çalışıyor o döndüren saklı yordamı yazabilirsiniz. Sorguları ile ilgili darboğazları (ileri ve geri veri aktarımı) yine istemci sonunda genellikle. Yuvalama çok derin almaz varsayarak, böyle bir şey yapmak için büyük bir sorun olmamalı:

CREATE FUNCTION get_nested_count( start INT ) RETURN INT
BEGIN
    DECLARE count INT 0;
    DECLARE current INT;
    current = start;
    DO
        count = count + 1;
        SELECT * FROM pages where "id"=current;
        current = pages.parent
    WHILE( pages.parent > 0 && pages.parent != start );
    RETURN count;
END

Süre üzerine ikinci çek dairesel döngü engeller (umarım: P)

Bu keyfi derinliğini işlemek için çeşit bir döngü gerektirir gidiyor.

Loop yazdığınız gibi prosedürel SQL (LOOP / ÇIKIŞ) şeklinde olabilir, ya da önuç kodu olabilir. Ön uç veritabanına yuvarlak gezileri nedeniyle yavaş olacaktır.

General solutions for handling Hierarchical MySQL data

WITH RECURSIVE depths(id, parentId, depth) AS (
    SELECT stuff.id, stuff.parentId, 0 FROM stuff WHERE parentId = 0
  UNION
    SELECT stuff.id, stuff.parentId, depths.depth + 1
      FROM stuff INNER JOIN depths
        ON stuff.parentId = depths.id
) SELECT * FROM depths;

Tabii ki, MySQL, SQL-99 bulunuyor WITH RECURSIVE desteklemez, ama kesinlikle yinelenen aynı şeyi yapabilirdi. Belki de derinliklerinde bir tablo tutmak, ya da mevcut tabloya bir sütun eklemek gerekir.

Sahip tablosunun tür bir Adjacency List adlandırılır. Bu bir komşuluk listesinde keyfi bir derinlik sorgu MySQL mümkün değildir.

Bunun için olağan tedavi (iç içe setleri kullanmak istemiyorsanız verilen ve sizin db şema kontrolü var) düğüm satırda bir alan olarak düğümün derinliği saklamak (veya yolunu temsil sınırlandırılmış bir dize saklamak için düğüme). Eğer tablo yapısı denetim yok olduğunda, en iyi bahis parent_id = 0 vurur kadar sorgulayan bir komut dosyası oluşturmak için

Sen böyle bir şey yapabilirdi. Bu tam değil ama bu size SQL Server Ortak tablo ifadeleri kullanarak sorunu çözmek için nasıl bir fikir verebilir.

WITH [CTE]
  AS ( SELECT * FROM TieredTable t1
    		UNION ALL
    	SELECT t1.* FROM [CTE] cte, TieredTable t1
         WHERE t1.[Parent_Id] = cte.[Id] )
SELECT COUNT(*) AS cnt, id 
  FROM [CTE] 
 WHERE parent_id <> 0
 GROUP BY id

İşte tablo var;

CREATE TABLE [dbo].[TieredTable](
    [id] [int] NULL,
    [parent_id] [int] NULL,
    [stuff] [varchar](50) NULL
) 

id      pid     stuff
10  0	One
20  10	Two
30  20	Three

Bu sorgu, herhangi bir düğüm için size derinlik düzeyini dönecektir:

SELECT  COUNT(*)
FROM    (
        SELECT  id,
                @r :=
                (
                SELECT  parent
                FROM    mytable
                WHERE   id = @r
                        AND id <> 0
                ) AS _parent
        FROM    (
                SELECT  @r := 56
                ) vars,
                mytable
        WHERE   @r IS NOT NULL
        ) q
WHERE   _parent IS NOT NULL;

Düğüm id İstediğiniz ile @r := 56 olarak değiştirin.