একটি পুনরাবৃত্ত স্ব-যোগদানের সহজ উপায়?


102

এসকিউএল সার্ভারে একটি পুনরাবৃত্ত স্ব-যোগদানের সহজ উপায় কী? আমার এই মত একটি টেবিল আছে:

PersonID | Initials | ParentID
1          CJ         NULL
2          EB         1
3          MB         1
4          SW         2
5          YT         NULL
6          IS         5

এবং আমি কেবল নির্দিষ্ট ব্যক্তির সাথে শুরু করে একটি শ্রেণিবিন্যাস সম্পর্কিত রেকর্ডগুলি পেতে সক্ষম হতে চাই। সুতরাং আমি যদি ব্যক্তিবর্গ = 1 দ্বারা সিজে-র হায়ারার্কিকে অনুরোধ করি তবে আমি পেতাম:

PersonID | Initials | ParentID
1          CJ         NULL
2          EB         1
3          MB         1
4          SW         2

এবং ইসির জন্য আমি পেয়েছি:

PersonID | Initials | ParentID
2          EB         1
4          SW         2

আমি এই বিষয়ে কিছুটা আটকে আছি, একসাথে যোগদানের ভিত্তিতে স্থির-গভীরতার প্রতিক্রিয়া বাদে কীভাবে এটি করা যায় তা ভাবতে পারি না। এটি হ'ল এটি হবে কারণ আমাদের অনেক স্তর থাকবে না তবে আমি এটি সঠিকভাবে করতে চাই।

ধন্যবাদ! ক্রিস


4
আপনি এসকিউএল সার্ভারের কোন সংস্করণ ব্যবহার করছেন? অর্থাত 2007, 2007, 2007?
boydc7

4
পুনরাবৃত্তিমূলক ক্যোয়ারী সম্পর্কিত এসও প্রশ্ন: স্ট্যাকওভারফ্লো.com
ওএমজি পনি

উত্তর:


115
WITH    q AS 
        (
        SELECT  *
        FROM    mytable
        WHERE   ParentID IS NULL -- this condition defines the ultimate ancestors in your chain, change it as appropriate
        UNION ALL
        SELECT  m.*
        FROM    mytable m
        JOIN    q
        ON      m.parentID = q.PersonID
        )
SELECT  *
FROM    q

ক্রম শর্ত যুক্ত করে, আপনি গাছের অর্ডার সংরক্ষণ করতে পারেন:

WITH    q AS 
        (
        SELECT  m.*, CAST(ROW_NUMBER() OVER (ORDER BY m.PersonId) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN AS bc
        FROM    mytable m
        WHERE   ParentID IS NULL
        UNION ALL
        SELECT  m.*,  q.bc + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY m.ParentID ORDER BY m.PersonID) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN
        FROM    mytable m
        JOIN    q
        ON      m.parentID = q.PersonID
        )
SELECT  *
FROM    q
ORDER BY
        bc

ORDER BYঅবস্থার পরিবর্তন করে আপনি ভাইবোনদের ক্রম পরিবর্তন করতে পারেন।


7
+1 বাদে ক্রিসের PersonID = theIdYouAreLookingForপরিবর্তে প্রয়োজন হবে ParentID IS NULL
হেইনজি

আমি এসও-তে একটি নতুন প্রশ্ন পোস্ট করেছি, স্ট্যাকওভারফ্লো.com
কিশোর কুমার

@ অ্যারোনিনাস: প্যারেন্ট নোডটি ক্লোজে শীর্ষস্থানীয় (অ্যাঙ্কর) কোয়েরি দ্বারা সংজ্ঞায়িত করা হয়েছে WITH। আপনার যদি নির্দিষ্টকরণের প্রয়োজন হয় তবে দয়া করে sqlfiddle.com এ একটি ফিডল তৈরি করুন এবং লিঙ্কটি এখানে পোস্ট করুন।
কাসনসুই

রেফারেন্সের জন্য আমি "10.3.23-MariaDB-0 + deb10u1" ব্যবহার করছি
জোশ ম্যাকগি

@ জোশমিসজি: আপনি কেন কোনও পরিবর্তন ছাড়াই মারিয়াডিবিতে একটি এসকিউএল সার্ভার কোয়েরি কাজটি আশা করেছিলেন?
কাসনসুই

25

সিটিই ব্যবহার করে আপনি এটি এভাবে করতে পারেন

DECLARE @Table TABLE(
        PersonID INT,
        Initials VARCHAR(20),
        ParentID INT
)

INSERT INTO @Table SELECT     1,'CJ',NULL
INSERT INTO @Table SELECT     2,'EB',1
INSERT INTO @Table SELECT     3,'MB',1
INSERT INTO @Table SELECT     4,'SW',2
INSERT INTO @Table SELECT     5,'YT',NULL
INSERT INTO @Table SELECT     6,'IS',5

DECLARE @PersonID INT

SELECT @PersonID = 1

;WITH Selects AS (
        SELECT *
        FROM    @Table
        WHERE   PersonID = @PersonID
        UNION ALL
        SELECT  t.*
        FROM    @Table t INNER JOIN
                Selects s ON t.ParentID = s.PersonID
)
SELECT  *
FROm    Selects

4
গুরুত্বপূর্ণ WHERE ব্যক্তিত্বের সাথে সম্পূর্ণ সম্পূর্ণ উত্তর = @ পার্সনআইডি
অলি বি

5

বড় টেবিলের পরিবর্তনের সাথে কোসনোই ক্যোয়ারী। তারপরে আরও বাচ্চাদের সাথে পিতামাতারা 10: স্ট্রিং (5) সারি_নাম্বার () হিসাবে ফর্ম্যাট করছেন

প্রশ্নোত্তর হিসাবে 
        (
        নির্বাচন করুন মি। *, ক্যাসেট (আরআর (ROW_NUMBER () ওভার (অর্ডার দ্বারা অর্ডার)), 5) ভোচারার (ম্যাক্স)) ল্যাটিন ল্যাটিন 1_ জেনারাল_বিন হিসাবে বিসি
        # টিএম থেকে
        যেখানে প্যারেন্টিড = 0
        ইউনিয়ন সব
        নির্বাচন করুন মি। *, কি.বিসি + ''। + স্ট্রিং (ROW_NUMBER () ওভার (এম। পার্টনমেন্ট দ্বারা পার্টিশন এম। অর্ডার্নাম), 5) ল্যাটিন 1_ জেনারাল_বিআইএন কল করুন
        # টিএম থেকে
        যোগ দিন
        চালু আছে m.parentID = q.DBID
        )
নির্বাচন করুন *
থেকে কিউ
অর্ডার দ্বারা
        বিসি


2

এসকিউএল 2005 বা তার পরে, সিটিই হ'ল দেখানো উদাহরণ অনুসারে যাওয়ার মানক উপায়।

এসকিউএল 2000, আপনি এটি ইউডিএফ ব্যবহার করে করতে পারেন -

CREATE FUNCTION udfPersonAndChildren
(
    @PersonID int
)
RETURNS @t TABLE (personid int, initials nchar(10), parentid int null)
AS
begin
    insert into @t 
    select * from people p      
    where personID=@PersonID

    while @@rowcount > 0
    begin
      insert into @t 
      select p.*
      from people p
        inner join @t o on p.parentid=o.personid
        left join @t o2 on p.personid=o2.personid
      where o2.personid is null
    end

    return
end

(যা ২০০৫ সালে কাজ করবে, এটি কেবল এটি করার আদর্শ উপায় নয় That এটি বলেছে, যদি আপনি কাজ করার সহজ উপায় খুঁজে পান তবে এটির সাথে চালান)

আপনার যদি সত্যই এসকিউএল 7 এ করার দরকার হয় তবে আপনি উপরের দিকে প্রায় কোনও স্প্রোকে করতে পারেন তবে এটি থেকে নির্বাচন করতে পারেন না - এসকিউএল 7 ইউডিএফ সমর্থন করে না।


2

সিটিই পুনরাবৃত্তি ধারণাটি বুঝতে সহায়তা করতে নিম্নলিখিত চেক করুন

DECLARE
@startDate DATETIME,
@endDate DATETIME

SET @startDate = '11/10/2011'
SET @endDate = '03/25/2012'

; WITH CTE AS (
    SELECT
        YEAR(@startDate) AS 'yr',
        MONTH(@startDate) AS 'mm',
        DATENAME(mm, @startDate) AS 'mon',
        DATEPART(d,@startDate) AS 'dd',
        @startDate 'new_date'
    UNION ALL
    SELECT
        YEAR(new_date) AS 'yr',
        MONTH(new_date) AS 'mm',
        DATENAME(mm, new_date) AS 'mon',
        DATEPART(d,@startDate) AS 'dd',
        DATEADD(d,1,new_date) 'new_date'
    FROM CTE
    WHERE new_date < @endDate
    )
SELECT yr AS 'Year', mon AS 'Month', count(dd) AS 'Days'
FROM CTE
GROUP BY mon, yr, mm
ORDER BY yr, mm
OPTION (MAXRECURSION 1000)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.