2009-07-16 10 views
5

मुझे SQL में "पेड़ की तरह" क्वेरी (हम इसे क्या कहते हैं?) करने में कुछ परेशानी हो रही है। (समूह)एसक्यूएल "पेड़ की तरह" क्वेरी - अधिकांश मूल समूह

DB diagram http://img197.imageshack.us/img197/8721/44060572.jpg MSSQL सर्वर 2005 का उपयोग करना, लक्ष्य सबसे मूल समूह मिल रहा है: -

नीचे मेरी आरेख पर एक नजर डालें (अत: क्षमा करें मेज और स्तंभ नाम डेनिश में हैं) , प्रत्येक ग्राहक (कुंडे) के लिए।

प्रत्येक समूह में कई अभिभावक समूह और कई बच्चे समूह हो सकते हैं।

और, मैं भी कैसे इस तरह के पेड़ प्रदर्शित करने के लिए जानना चाहते हैं:

 
Customer 1 
    - Parent group 1 
     - Child group 1 
     - ChildChild group n 
     - Child group n 
    - Parent group n 
     - ... 
     - ... 
Customer n 
    - ... 

एक और सवाल:

कैसे क्वेरी देखो सभी के लिए सभी समूहों प्राप्त करने के लिए करता है ग्राहकों? अभिभावक और बाल समूह।

+1

मैं डेटा के इस प्रकार के लिए एक आम नाम का मानना ​​है कि "श्रेणीबद्ध" है और आप चाहते हैं "शीर्ष पूर्वज।" आप पुनरावर्ती प्रश्नों का उपयोग कर सकते हैं (ऐसा करने के लिए http://www.codeproject.com/KB/architecture/RoleBasedSecurity.aspx देखें)। – Blixt

उत्तर

4

मैं इसे जो सेल्को से बेहतर नहीं कह सकता। समस्या यह है कि आमतौर पर निर्मित मॉडल पदानुक्रम बनाने के लिए खुद को उधार नहीं देते हैं, और उन मॉडलों को आपके पदानुक्रम की विशेषताओं को ध्यान में रखना होगा। क्या यह बहुत गहरा है? क्या यह बहुत व्यापक है? क्या यह संकीर्ण और उथला है?

व्यापक और उथले पेड़ों पर सफलता की एक कुंजी है स्तंभ के पदानुक्रम में पूर्ण पथ होना, जैसे सेल्को पहले लिंक में उल्लेख करता है।

+0

मैंने पहले ही उन लेखों को देखा है। मुझे जो नहीं मिलता है वह है कि मैं इसे अपनी स्कीमा पर कैसे लागू कर सकता हूं। –

+0

आप सेल्को से बेहतर कहने में सक्षम नहीं हो सकते हैं, लेकिन आपने निश्चित रूप से यह अच्छा कहा है :) –

+0

मैं कह रहा हूं कि आपकी स्कीमा में संशोधन किए बिना, आपको अच्छा प्रदर्शन करने में कठिनाई होगी। –

1

T-SQL में, आप थोड़ी देर के पाश लिख सकते हैं। Untested:

@group = <starting group> 
WHILE (EXISTS(SELECT * FROM Gruppe_Gruppe WHERE [email protected])) 
BEGIN 
    SELECT @group=ParentGruppeId FROM Gruppe_Gruppe WHERE [email protected] 
END 
+0

को अद्यतन/डालने के दौरान पूर्णपैथ को अद्यतन/उत्पन्न करने की लागत पर, पूर्ण रूप से शीर्ष समूह के लिए कुंडे में पूर्णपैथ कॉलम जोड़ूंगा, क्या यह काम करेगा ? क्या होगा अगर @ ग्रुप माता-पिता है? –

+0

आपका मतलब है, अगर @ ग्रुप के पास अब कोई अभिभावक समूह नहीं है? लूप दर्ज नहीं किया गया है, और परिणाम @ समूह है, जो मैं समझता हूं कि आप क्या चाहते हैं। –

+0

आह हाँ। मेरी गलती। तब आप प्रत्येक ग्राहक के लिए सबसे अधिक मूल समूह कैसे पाएंगे? एक से अधिक हो सकते हैं। –

1

हम SQL Server 2000 का उपयोग करें और वहाँ एसक्यूएल पुस्तकें ऑनलाइन में एक ढेर का उपयोग कर ढांचे के विस्तार का एक उदाहरण है, मैं अपने ईआरपी प्रणाली के लिए वेरिएंट की एक संख्या में लिखा है

http://support.microsoft.com/kb/248915

मैं इकट्ठा एक मूल निवासी विधि एसक्यूएल 2005 भीतर CTE का उपयोग कर है कि वहाँ लेकिन मैं इसे अपने आप

5

इस्तेमाल नहीं किया है आप तेज़ी से निर्माण करने के लिए "पूर्ण पथ" स्तंभ CTE के उपयोग कर सकते हैं

--DROP TABLE Gruppe, Kunde, Gruppe_Gruppe, Kunde_Gruppe 
CREATE TABLE Gruppe (
    Id     INT PRIMARY KEY 
    , Name    VARCHAR(100) 
    ) 
CREATE TABLE Kunde (
    Id     INT PRIMARY KEY 
    , Name    VARCHAR(100) 
    ) 
CREATE TABLE Gruppe_Gruppe (
    ParentGruppeId  INT 
    , ChildGruppeId  INT 
    ) 
CREATE TABLE Kunde_Gruppe (
    KundeId    INT 
    , GruppeId   INT 
    ) 

INSERT  Gruppe 
VALUES  (1, 'Group 1'), (2, 'Group 2'), (3, 'Group 3') 
      , (4, 'Sub-group A'), (5, 'Sub-group B'), (6, 'Sub-group C'), (7, 'Sub-group D') 

INSERT  Kunde 
VALUES  (1, 'Kunde 1'), (2, 'Kunde 2'), (3, 'Kunde 3') 

INSERT  Gruppe_Gruppe 
VALUES  (1, 4), (1, 5), (1, 7) 
      , (2, 6), (2, 7) 
      , (6, 1) 

INSERT  Kunde_Gruppe 
VALUES  (1, 1), (1, 2) 
      , (2, 3), (2, 4) 

;WITH  CTE 
AS   (
      SELECT  CONVERT(VARCHAR(1000), REPLACE(CONVERT(CHAR(5), k.Id), ' ', 'K')) AS TheKey 
         , k.Name  AS Name 
      FROM  Kunde k 

      UNION ALL 

      SELECT  CONVERT(VARCHAR(1000), REPLACE(CONVERT(CHAR(5), x.KundeId), ' ', 'K') 
          + REPLACE(CONVERT(CHAR(5), g.Id), ' ', 'G')) AS TheKey 
         , g.Name 
      FROM  Gruppe g 
      JOIN  Kunde_Gruppe x 
      ON   g.Id = x.GruppeId 

      UNION ALL 

      SELECT  CONVERT(VARCHAR(1000), p.TheKey + REPLACE(CONVERT(CHAR(5), g.Id), ' ', 'G')) AS TheKey 
         , g.Name 
      FROM  Gruppe g 
      JOIN  Gruppe_Gruppe x 
      ON   g.Id = x.ChildGruppeId 
      JOIN  CTE p 
      ON   REPLACE(CONVERT(CHAR(5), x.ParentGruppeId), ' ', 'G') = RIGHT(p.TheKey, 5) 
      WHERE  LEN(p.TheKey) < 32 * 5 
      ) 
SELECT  * 
      , LEN(TheKey)/5 AS Level 
FROM  CTE c 
ORDER BY c.TheKey 

यदि आपके पास बहुत सारे पाठ बनाम दुर्लभ संशोधन हैं तो प्रदर्शन उप-इष्टतम हो सकता है।

3

मैं ऐसे समाधान के साथ आया जो प्रत्येक ग्राहक के लिए सभी समूहों को सूचीबद्ध करने की समस्या हल करता है। अभिभावक और बाल समूह।

आपको क्या लगता है?

 
WITH GroupTree 
AS 
(
    SELECT kg.KundeId, g.Id GruppeId 
    FROM ActiveDirectory.Gruppe g 
    INNER JOIN ActiveDirectory.Kunde_Gruppe kg ON g.Id = kg.GruppeId 
    AND (EXISTS (SELECT * FROM ActiveDirectory.Gruppe_Gruppe WHERE ParentGruppeId = g.Id) 
    OR NOT EXISTS (SELECT * FROM ActiveDirectory.Gruppe_Gruppe WHERE ParentGruppeId = g.Id)) 

    UNION ALL 

    SELECT GroupTree.KundeId, gg.ChildGruppeId 
    FROM ActiveDirectory.Gruppe_Gruppe gg 
    INNER JOIN GroupTree ON gg.ParentGruppeId = GroupTree.GruppeId 
) 
SELECT KundeId, GruppeId 
FROM GroupTree 

OPTION (MAXRECURSION 32767) 
2

कुछ इस तरह के बारे में कैसे:

DECLARE @Customer TABLE(
     CustomerID INT IDENTITY(1,1), 
     CustomerName VARCHAR(MAX) 
) 

INSERT INTO @Customer SELECT 'Customer1' 
INSERT INTO @Customer SELECT 'Customer2' 
INSERT INTO @Customer SELECT 'Customer3' 

DECLARE @CustomerTreeStructure TABLE(
     CustomerID INT, 
     TreeItemID INT 
) 

INSERT INTO @CustomerTreeStructure (CustomerID,TreeItemID) SELECT 1, 1 
INSERT INTO @CustomerTreeStructure (CustomerID,TreeItemID) SELECT 2, 12 
INSERT INTO @CustomerTreeStructure (CustomerID,TreeItemID) SELECT 3, 1 
INSERT INTO @CustomerTreeStructure (CustomerID,TreeItemID) SELECT 3, 12 

DECLARE @TreeStructure TABLE(
     TreeItemID INT IDENTITY(1,1), 
     TreeItemName VARCHAR(MAX), 
     TreeParentID INT 
) 

INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001', NULL 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001', 1 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.001', 2 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.002', 2 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.003', 2 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.002', 1 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.003', 1 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.003.001', 7 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.002.001', 4 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.002.002', 4 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '001.001.002.003', 4 

INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '002', NULL 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '002.001', 12 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '002.001.001', 13 
INSERT INTO @TreeStructure (TreeItemName,TreeParentID) SELECT '002.001.002', 13 

;WITH Structure AS (
    SELECT TreeItemID, 
      TreeItemName, 
      TreeParentID, 
      REPLICATE('0',5 - LEN(CAST(TreeItemID AS VARCHAR(MAX)))) + CAST(TreeItemID AS VARCHAR(MAX)) + '\\' TreePath 
    FROM @TreeStructure ts 
    WHERE ts.TreeParentID IS NULL 
    UNION ALL 
    SELECT ts.*, 
      s.TreePath + REPLICATE('0',5 - LEN(CAST(ts.TreeItemID AS VARCHAR(5)))) + CAST(ts.TreeItemID AS VARCHAR(5)) + '\\' TreePath 
    FROM @TreeStructure ts INNER JOIN 
      Structure s ON ts.TreeParentID = s.TreeItemID 
) 

SELECT c.CustomerName, 
     Children.TreeItemName, 
     Children.TreePath 
FROM @Customer c INNER JOIN 
     @CustomerTreeStructure cts ON c.CustomerID = cts.CustomerID INNER JOIN 
     Structure s ON cts.TreeItemID = s.TreeItemID INNER JOIN 
     (
      SELECT * 
      FROM Structure 
     ) Children ON Children.TreePath LIKE s.TreePath +'%' 
ORDER BY 1,3 
OPTION (MAXRECURSION 0) 
संबंधित मुद्दे