পার্টিশন থেকে পৃথক এসকিউএল গণনা


10

আমার কাছে দুটি কলাম সহ একটি টেবিল রয়েছে, আমি কল_বি ওপরে (শর্তাধীন) কল_এতে স্বতন্ত্র মানগুলি গণনা করতে চাই।

MyTable

Col_A | Col_B 
A     | 1
A     | 1
A     | 2
A     | 2
A     | 2
A     | 3
b     | 4
b     | 4
b     | 5

প্রত্যাশিত ফলাফল

Col_A   | Col_B | Result
A       | 1     | 3
A       | 1     | 3
A       | 2     | 3
A       | 2     | 3
A       | 2     | 3
A       | 3     | 3
b       | 4     | 2
b       | 4     | 2
b       | 5     | 2

আমি নিম্নলিখিত কোড চেষ্টা করেছিলাম

select *, 
count (distinct col_B) over (partition by col_A) as 'Result'
from MyTable

গণনা (স্বতন্ত্র কল_বি) কাজ করছে না। স্বতন্ত্র মানগুলি গণনা করার জন্য আমি কীভাবে গণনা ফাংশনটি আবার লিখতে পারি?

উত্তর:


18

আমি এটি এইভাবে করব:

SELECT      *
FROM        #MyTable AS mt
CROSS APPLY (   SELECT COUNT(DISTINCT mt2.Col_B) AS dc
                FROM   #MyTable AS mt2
                WHERE  mt2.Col_A = mt.Col_A
                -- GROUP BY mt2.Col_A 
            ) AS ca;

GROUP BYপ্রশ্নটিতে প্রদত্ত ডেটা দিয়ে এই ধারাটি অপ্রয়োজনীয়, তবে আপনাকে আরও কার্যকর সম্পাদনের পরিকল্পনা দিতে পারে। ফলো-আপ প্রশ্নোত্তর দেখুন এবং একটি ক্রস অ্যাপ্লিকেশন বাহ্যিক যোগদানের উত্পাদন করে

ওভার ক্লজ বর্ধনের অনুরোধের জন্য ভোটদান বিবেচনা করুন - প্রতিক্রিয়া সাইটে সামগ্রিক ফাংশনগুলির জন্য DISTINCT ধারাটি যদি আপনি চান যে এই বৈশিষ্ট্যটি এসকিউএল সার্ভারে যুক্ত করা হয়।


6

আপনি এটি ব্যবহার করে অনুকরণ করতে পারেন dense_rank, এবং তারপরে প্রতিটি পার্টিশনের জন্য সর্বোচ্চ পদটি চয়ন করতে পারেন:

select col_a, col_b, max(rnk) over (partition by col_a)
from (
    select col_a, col_b
        , dense_rank() over (partition by col_A order by col_b) as rnk 
    from #mytable
) as t    

col_bহিসাবে একই ফলাফল পেতে আপনাকে কোনও নাল বাদ দিতে হবে COUNT(DISTINCT)


6

এটি একরকমভাবে লেনার্টের সমাধানের জন্য একটি এক্সটেনশন , তবে এটি এতই কুৎসিত যে আমি এটিকে সম্পাদনা হিসাবে প্রস্তাব করার সাহস পাই না। এখানে লক্ষ্যটি কোনও উত্পন্ন টেবিল ছাড়াই ফলাফল পাওয়া the এটির প্রয়োজন নেই এবং কোয়েরির কদর্যতার সাথে একত্রে পুরো প্রচেষ্টাটি একটি ব্যর্থ প্রচেষ্টা বলে মনে হতে পারে। আমি এখনও এটি অনুশীলন হিসাবে করতে চেয়েছিলাম, এবং এখন আমার ফলাফলটি ভাগ করে নিতে চাই:

SELECT
  Col_A,
  Col_B,
  DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
                + DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
                - 1
                - CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
                  WHEN COUNT(  *  ) OVER (PARTITION BY Col_A)
                  THEN 0
                  ELSE 1
                  END
FROM
  dbo.MyTable
;

গণনার মূল অংশটি হ'ল (এবং আমি সবার আগে ধারণাটি আমার নয়, আমি অন্যত্র এই কৌশল সম্পর্কে শিখেছি):

  DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- 1

এই মানটি কোনও পরিবর্তন ছাড়াই ব্যবহার করা যেতে পারে যদি মানগুলিতে Col_Bকখনও শূন্য না হওয়ার গ্যারান্টি দেওয়া হয়। যদি কলামটিতে নালাগুলি থাকতে পারে তবে আপনাকে তার জন্য অ্যাকাউন্ট করতে হবে এবং CASEএক্সপ্রেশনটি ঠিক এটির জন্যই রয়েছে। এটি পার্টিশন প্রতি সারি সংখ্যা পার্টিশন প্রতি Col_Bমান সংখ্যার সাথে তুলনা করে । যদি সংখ্যাগুলি পৃথক হয় তবে এর অর্থ হ'ল কিছু সারিগুলির শূন্যতা রয়েছে Col_Bএবং তাই প্রাথমিক গণনা ( DENSE_RANK() ... + DENSE_RANK() - 1) 1 দ্বারা হ্রাস করা দরকার।

নোট করুন যেহেতু - 1মূল সূত্রটির অংশ, তাই আমি এটি ছেড়ে যেতে পছন্দ করেছি। তবে CASEপুরো সমাধানটিকে কম কুৎসিত দেখানোর ব্যর্থ প্রচেষ্টাতে এটি আসলে প্রকাশের সাথে সংযুক্ত করা যেতে পারে :

SELECT
  Col_A,
  Col_B,
  DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
                + DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
                - CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
                  WHEN COUNT(  *  ) OVER (PARTITION BY Col_A)
                  THEN 1
                  ELSE 2
                  END
FROM
  dbo.MyTable
;

ডিবিফিডাল লোগোডিবি <> fiddle.uk এ এই লাইভ ডেমোটি সমাধানের উভয় প্রকারের পরীক্ষা করতে ব্যবহার করা যেতে পারে।


2
create table #MyTable (
Col_A varchar(5),
Col_B int
)

insert into #MyTable values ('A',1)
insert into #MyTable values ('A',1)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',3)

insert into #MyTable values ('B',4)
insert into #MyTable values ('B',4)
insert into #MyTable values ('B',5)


;with t1 as (

select t.Col_A,
       count(*) cnt
 from (
    select Col_A,
           Col_B,
           count(*) as ct
      from #MyTable
     group by Col_A,
              Col_B
  ) t
  group by t.Col_A
 )

select a.*,
       t1.cnt
  from #myTable a
  join t1
    on a.Col_A = t1.Col_a

1

বিকল্প যদি আপনি আমার মতো সম্পর্কযুক্ত subqueries (এরিক ডার্লিং এর উত্তর) এবং সিটিই (কেভিনহোটের উত্তর) থেকে হালকাভাবে অ্যালার্জি হন।

সচেতন হন যে যখন নালগুলি মিশ্রণে ফেলে দেওয়া হয় তখন এগুলির কোনওটিই আপনি কীভাবে পছন্দ করবেন তা কাজ করতে পারে না। (তবে এটির স্বাদে পরিবর্তন করা মোটামুটি সহজ)

সাধারণ কেস:

--ignore the existence of nulls
SELECT [mt].*, [Distinct_B].[Distinct_B]
FROM #MyTable AS [mt]

INNER JOIN(
    SELECT [Col_A], COUNT(DISTINCT [Col_B]) AS [Distinct_B]
    FROM #MyTable
    GROUP BY [Col_A]
) AS [Distinct_B] ON
    [mt].[Col_A] = [Distinct_B].[Col_A]
;

উপরের মতো একই, তবে নাল হ্যান্ডলিংয়ের জন্য কী পরিবর্তন করা উচিত তার মন্তব্যে:

--customizable null handling
SELECT [mt].*, [Distinct_B].[Distinct_B]
FROM #MyTable AS [mt]

INNER JOIN(
    SELECT 

    [Col_A],

    (
        COUNT(DISTINCT [Col_B])
        /*
        --uncomment if you also want to count Col_B NULL
        --as a distinct value
        +
        MAX(
            CASE
                WHEN [Col_B] IS NULL
                THEN 1
                ELSE 0
            END
        )
        */
    )
    AS [Distinct_B]

    FROM #MyTable
    GROUP BY [Col_A]
) AS [Distinct_B] ON
    [mt].[Col_A] = [Distinct_B].[Col_A]
/*
--uncomment if you also want to include Col_A when it's NULL
OR
([mt].[Col_A] IS NULL AND [Distinct_B].[Col_A] IS NULL)
*/
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.