Domanda

Sto cercando di costruire un impianto che consente l'esecuzione di query per i dati con il filtraggio gerarchica. Ho un paio di idee su come ho intenzione di andare su di esso, ma chiedevo se ci sono eventuali raccomandazioni o suggerimenti che potrebbero essere più efficiente.

Per fare un esempio immaginare che un utente sta cercando un lavoro. Le aree di lavoro sarebbe il seguente.

1: Scotland
2: --- West Central
3: ------ Glasgow
4: ------ Etc
5: --- North East
6: ------ Ayrshire
7: ------ Etc

Un utente può cercare specifica (cioè Glasgow) o in una zona più ampia (cioè Scozia).

I due approcci sto considerando sono:

  1. mantenere una nota di bambini nel database per ogni record (vale a dire cat 1 avrebbe 2, 3, 4 nei suoi figli di campo) e query che record con un SELECT * FROM Jobs WHERE Category IN Areas.childrenField.
  2. Utilizzare una funzione ricorsiva per trovare tutti i risultati che hanno una relazione con l'area selezionata.

I problemi che vedo da entrambi sono:

  1. Tenendo questi dati nel db significherà dover tenere traccia di tutte le modifiche alla struttura.
  2. La ricorsione è lento e inefficent.

Tutte le idee, suggerimenti o raccomandazioni sul miglior approccio? Sto usando C # ASP.NET con MSSQL 2005 DB.

È stato utile?

Soluzione

Ecco un approccio che ho visto usato:

Creare un campo varchar (max) chiamato hierarchyid. Genera ids base per tutti gli oggetti di root. Per ogni oggetto figlio generare un id e anteporre con il genitore (s) id.

Esempio Tabella

ID(PK) HierarchyID Area
1       sl           Scotland 
2       slwc        West Central
3       slwcgg       Glasgow 

Esempio Query

SELECT * FROM Areas Where HierarchyID LIKE 'sl%'

Altri suggerimenti

Si dovrebbe usare set nidificati. Ecco un'implementazione in MySQL. http://mikehillyer.com/articles/managing-hierarchical-data-in -mysql /

È possibile utilizzare espressioni di tabella comuni per fare query ricorsive. Trovo questa tecnica molto potente, facile da leggere e facile da mantenere.

Che ne dici di questo?

Tabella =>

Id ParentId Nome

Nizza semplice tabella?

Poi come su qualche bel pezzo complicato pf SQL per andare con quella? (CTE roccia credo)

public object FetchCategoryTree()
{
    var sql = @"SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

    WITH AreaTree (ID, Name, ParentID, OrgLevel, SortKey) AS
    (
        -- Create the anchor query. This establishes the starting
        -- point
        SELECT
            a.ID,
            cast('---- ' + a.Name as varchar(255)),
            a.ParentID,
            cast('----' as varchar(55)),
            CAST(a.ID AS VARBINARY(900))
        FROM dbo.Area a
        WHERE a.ParentID is null
        UNION ALL
        -- Create the recursive query. This query will be executed
        -- until it returns no more rows
        SELECT
            a.ID,
            cast('----' + b.OrgLevel + '  ' + a.Name as varchar(255)),
            a.ParentID,
            cast(b.OrgLevel+ '----' as varchar(55)),
            CAST(b.SortKey + CAST (a.ID AS BINARY(4)) AS VARBINARY(900))
        FROM dbo.Area a
                INNER JOIN AreaTree b ON a.ParentID = b.ID
    )
    SELECT * FROM AreaTree
    ORDER BY SortKey";

    return FetchObject(sql);
}

Ora, questo fa qualche magia SQL che non sono troppo sicuro di. Tuttavia in parole povere prende fondamentalmente la prima parte della query radice. Poi si torna al tavolo ed esegue la seconda parte con la risposta della prima parte attraverso un join, e continua a fare per ancora non si può trovare nessuna più partite, fondamentalmente un grande anello. E 'piuttosto veloce pure.

Si otterrà il fuori un gruppo di righe con una chiave di ordinamento in allegato. Una volta che si ordina la query la chiave di ordinamento si otterrà la risposta del tipo:

 ---- parent 1
 -------- child 1
 -------- child 2
 ------------ child 2.1
 ---- parent 2
 -------- etc

Potrebbe essere quello che stai cercando?

Io uso modello ad albero di Joe Celko per la gerarchia imposta sulle vendite (stato / provincia / città / vari) nella nostra applicazione e funziona bene.

Il tuo "trovare un lavoro in questo settore o al di sotto" di query sarebbe simile a questa:

SELECT * FROM Jobs WHERE Jobs.AreaID IN
(SELECT P1.AreaID
FROM Areas AS P1, Areas AS P2
WHERE P1.lft BETWEEN P2.lft AND P2.rgt
AND P2.Areas.AreaID = @selectedAreaID)

Celko Albero in SQL articolo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top