আপনি কি ওভার ক্লজ সহ COUNT DISTINCT ব্যবহার করতে পারেন?


25

আমি নিম্নলিখিত কোয়েরিটির কার্যকারিতা উন্নত করার চেষ্টা করছি:

        UPDATE  [#TempTable]
        SET     Received = r.Number
        FROM    [#TempTable] 
        INNER JOIN (SELECT  AgentID,
                            RuleID,
                            COUNT(DISTINCT (GroupId)) Number
                    FROM    [#TempTable]
                    WHERE   Passed = 1
                    GROUP BY AgentID,
                            RuleID
                   ) r ON r.RuleID = [#TempTable].RuleID AND
                          r.AgentID = [#TempTable].AgentID                            

বর্তমানে আমার পরীক্ষার ডেটা সহ এটি প্রায় এক মিনিট সময় নেয়। আমার কাছে এই কোয়েরিটি থাকা সমস্ত স্টোরেজ পদ্ধতিতে পরিবর্তনের ক্ষেত্রে সীমিত পরিমাণের ইনপুট রয়েছে তবে আমি সম্ভবত তাদের এই একটি ক্যোয়ারীটি পরিবর্তন করতে পারি। অথবা একটি সূচক যুক্ত করুন। আমি নিম্নলিখিত সূচকটি যুক্ত করার চেষ্টা করেছি:

CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)

এবং এটি আসলে ক্যোয়ারির সময় দ্বিগুণ করে। নন-ক্লাস্টার্ড ইনডেক্সের সাথে আমি একই প্রভাব পেয়েছি।

আমি কোনও প্রভাব ছাড়াই নীচে এটি পুনরায় লেখার চেষ্টা করেছি।

        WITH r AS (SELECT  AgentID,
                            RuleID,
                            COUNT(DISTINCT (GroupId)) Number
                    FROM    [#TempTable]
                    WHERE   Passed = 1
                    GROUP BY AgentID,
                            RuleID
            ) 
        UPDATE  [#TempTable]
        SET     Received = r.Number
        FROM    [#TempTable] 
        INNER JOIN r 
            ON r.RuleID = [#TempTable].RuleID AND
               r.AgentID = [#TempTable].AgentID                            

পরবর্তী আমি এইভাবে একটি উইন্ডোং ফাংশন ব্যবহার করার চেষ্টা করেছি।

        UPDATE  [#TempTable]
        SET     Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END)) 
                    OVER (PARTITION BY AgentId, RuleId)
        FROM    [#TempTable] 

এই সময়ে আমি ত্রুটি পেতে শুরু

Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.

সুতরাং আমার দুটি প্রশ্ন আছে। প্রথমে আপনি ওভারের ধারাটি দিয়ে একটি COUNT টি ডিসটিন্ট করতে পারবেন না বা আমি কেবল এটি ভুল লিখেছি? এবং দ্বিতীয়ত কেউ কি এমন উন্নতির পরামর্শ দিতে পারে যা আমি ইতিমধ্যে চেষ্টা করেছিলাম না? FYI এটি একটি এসকিউএল সার্ভার 2008 আর 2 এন্টারপ্রাইজ দৃষ্টান্ত।

সম্পাদনা: এখানে আসল বাস্তবায়ন পরিকল্পনার লিঙ্ক is আমার আরও উল্লেখ করা উচিত যে আমার বড় সমস্যাটি এই কোয়েরিটি 30-50 বার চালানো হচ্ছে।

https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772

সম্পাদনা 2: মন্তব্যগুলিতে অনুরোধ অনুসারে বিবৃতিটি সম্পূর্ণ লুপটি এখানে রয়েছে। আমি লুপের উদ্দেশ্য হিসাবে যিনি নিয়মিত এই সাথে কাজ করে তার সাথে চেক করছি।

DECLARE @Counting INT              
SELECT  @Counting = 1              

--  BEGIN:  Cascading Rule check --           
WHILE @Counting <= 30              
    BEGIN      

        UPDATE  w1
        SET     Passed = 1
        FROM    [#TempTable] w1,
                [#TempTable] w3
        WHERE   w3.AgentID = w1.AgentID AND
                w3.RuleID = w1.CascadeRuleID AND
                w3.RulePassed = 1 AND
                w1.Passed = 0 AND
                w1.NotFlag = 0      

        UPDATE  w1
        SET     Passed = 1
        FROM    [#TempTable] w1,
                [#TempTable] w3
        WHERE   w3.AgentID = w1.AgentID AND
                w3.RuleID = w1.CascadeRuleID AND
                w3.RulePassed = 0 AND
                w1.Passed = 0 AND
                w1.NotFlag = 1        

        UPDATE  [#TempTable]
        SET     Received = r.Number
        FROM    [#TempTable] 
        INNER JOIN (SELECT  AgentID,
                            RuleID,
                            COUNT(DISTINCT (GroupID)) Number
                    FROM    [#TempTable]
                    WHERE   Passed = 1
                    GROUP BY AgentID,
                            RuleID
                   ) r ON r.RuleID = [#TempTable].RuleID AND
                          r.AgentID = [#TempTable].AgentID                            

        UPDATE  [#TempTable]
        SET     RulePassed = 1
        WHERE   TotalNeeded = Received              

        SELECT  @Counting = @Counting + 1              
    END

উত্তর:


28

এই নির্মাণটি বর্তমানে এসকিউএল সার্ভারে সমর্থিত নয়। এটি (এবং আমার মতে) ভবিষ্যতের সংস্করণে প্রয়োগ করা যেতে পারে।

এই ঘাটতির প্রতিবেদন করে প্রতিক্রিয়ার আইটেমের তালিকাভুক্ত ওয়ার্কআরউন্ডগুলির মধ্যে একটি প্রয়োগ করা , আপনার ক্যোয়ারীটি আবার লিখতে পারে:

WITH UpdateSet AS
(
    SELECT 
        AgentID, 
        RuleID, 
        Received, 
        Calc = SUM(CASE WHEN rn = 1 THEN 1 ELSE 0 END) OVER (
            PARTITION BY AgentID, RuleID) 
    FROM 
    (
        SELECT  
            AgentID,
            RuleID,
            Received,
            rn = ROW_NUMBER() OVER (
                PARTITION BY AgentID, RuleID, GroupID 
                ORDER BY GroupID)
        FROM    #TempTable
        WHERE   Passed = 1
    ) AS X
)
UPDATE UpdateSet
SET Received = Calc;

ফলাফল কার্যকরকরণ পরিকল্পনাটি হ'ল:

পরিকল্পনা

এটি হ্যালোইন সুরক্ষা (স্ব-যোগদানের কারণে) এর জন্য একটি ইজিার টেবিল স্পুল এড়িয়ে যাওয়ার সুবিধা রয়েছে তবে এটি গণনা করতে এবং ফলকে SUM OVER (PARTITION BY)সমস্ত সারিতে প্রয়োগ করার জন্য একটি সাজানোর (উইন্ডোটির জন্য) এবং প্রায়শই অদক্ষ অলস টেবিল স্পুল নির্মাণের পরিচয় দেয় উইন্ডোতে। এটি অনুশীলনে কীভাবে সম্পাদন করে তা কেবল আপনি সম্পাদন করতে পারেন exercise

সামগ্রিক পদ্ধতির ভাল পারফরম্যান্স করা কঠিন। বড় আকারের কাঠামোর ক্ষেত্রে পুনরাবৃত্তভাবে আপডেটগুলি প্রয়োগ করা (বিশেষত একটি স্ব-যোগদানের ভিত্তিতে) ডিবাগিংয়ের জন্য ভাল হতে পারে তবে এটি দুর্বল পারফরম্যান্সের একটি রেসিপি। বারবার বড় স্ক্যান, মেমোরি স্পিল এবং হ্যালোইন ইস্যুগুলির কয়েকটি বিষয়। ইনডেক্সিং এবং (আরও) অস্থায়ী সারণীগুলি সহায়তা করতে পারে তবে খুব সতর্কতার সাথে বিশ্লেষণ করা দরকার বিশেষত যদি সূচকে প্রক্রিয়াতে অন্যান্য বিবৃতি দ্বারা আপডেট করা হয় (সূচিগুলি বজায় রাখা ক্যোয়ারী পরিকল্পনার পছন্দগুলিকে প্রভাবিত করে এবং I / O যোগ করে)।

শেষ পর্যন্ত, অন্তর্নিহিত সমস্যাটি সমাধান করা আকর্ষণীয় পরামর্শ কাজের জন্য তৈরি করবে তবে এটি এই সাইটের পক্ষে খুব বেশি। আমি আশা করি এই উত্তরটি যদিও পৃষ্ঠের প্রশ্নের সমাধান করবে।


মূল ক্যোয়ারির বিকল্প ব্যাখ্যা (আরও সারি আপডেট করার ফলাফল):

WITH UpdateSet AS
(
    SELECT 
        AgentID, 
        RuleID, 
        Received, 
        Calc = SUM(CASE WHEN Passed = 1 AND rn = 1 THEN 1 ELSE 0 END) OVER (
            PARTITION BY AgentID, RuleID) 
    FROM 
    (
        SELECT  
            AgentID,
            RuleID,
            Received,
            Passed,
            rn = ROW_NUMBER() OVER (
                PARTITION BY AgentID, RuleID, Passed, GroupID
                ORDER BY GroupID)
        FROM    #TempTable
    ) AS X
)
UPDATE UpdateSet
SET Received = Calc
WHERE Calc > 0;

পরিকল্পনা 2

দ্রষ্টব্য: বাছাই (মুদ্রা সরবরাহ করে) মুছে ফেলা ইজিগার স্পুল বা প্রয়োজনীয় কিছু হ্যালোইন সুরক্ষা সরবরাহ করার জন্য অন্য কোনও কিছুর পুনরুত্পাদন করতে পারে। বাছাই একটি ব্লকিং অপারেটর, সুতরাং এটি সম্পূর্ণ পর্যায়ে পৃথকীকরণ সরবরাহ করে।


6

Necromancing:

DENSE_RANK দ্বারা পার্টিশনের চেয়ে আলাদা একটি গণনা পৃথক করে তুলনামূলকভাবে সহজ:

;WITH baseTable AS
(
              SELECT 'RM1' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM1' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR2' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR2' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR3' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR2' AS ADR
)
,CTE AS
(
    SELECT RM, ADR, DENSE_RANK() OVER(PARTITION BY RM ORDER BY ADR) AS dr 
    FROM baseTable
)
SELECT
     RM
    ,ADR

    ,COUNT(CTE.ADR) OVER (PARTITION BY CTE.RM ORDER BY ADR) AS cnt1 
    ,COUNT(CTE.ADR) OVER (PARTITION BY CTE.RM) AS cnt2 
    -- Geht nicht / Doesn't work 
    --,COUNT(DISTINCT CTE.ADR) OVER (PARTITION BY CTE.RM ORDER BY CTE.ADR) AS cntDist
    ,MAX(CTE.dr) OVER (PARTITION BY CTE.RM ORDER BY CTE.RM) AS cntDistEmu 
FROM CTE

3
এর শব্দার্থবিজ্ঞানগুলি একই রকম নয় যেমন countকলামটি nlalable হয়। এটিতে যদি কোনও নাল থাকে তবে আপনার 1 টি বিয়োগ করা উচিত
মার্টিন স্মিথ

@ মার্টিন স্মিথ: দুর্দান্ত ক্যাচ স্পষ্টতই আপনাকে যুক্ত করতে হবে যেখানে নাল-মান রয়েছে তবে ADR নাল নয়।
Quandary
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.