একটি গ্রুপের উপর প্রতি কলামে সর্বশেষ নন-নুল মানগুলির সেটটি কীভাবে নির্বাচন করবেন?


9

আমি এসকিউএল সার্ভার 2016 ব্যবহার করছি এবং আমি যে ডেটা গ্রহণ করছি তাতে নিম্নলিখিত ফর্মটি রয়েছে।

CREATE TABLE #tab (cat CHAR(1), t CHAR(2), val1 INT, val2 CHAR(1));

INSERT INTO #tab VALUES 
    ('A','Q1',2,NULL),('A','Q2',NULL,'P'),('A','Q3',1,NULL),('A','Q3',NULL,NULL),
    ('B','Q1',5,NULL),('B','Q2',NULL,'P'),('B','Q3',NULL,'C'),('B','Q3',10,NULL);

SELECT *
FROM    #tab;

এখানে চিত্র বর্ণনা লিখুন

আমি কলামগুলিতে সর্বশেষ নন-মানগুলি অর্জন করতে চাই val1এবং val2গোষ্ঠী অনুসারে catও এর দ্বারা আদেশ পেয়েছি t। আমি যে ফলাফলটি চাইছি তা হ'ল

cat  val1 val2
A    1    P
B    10   C

আমার কাছে আসা সবচেয়ে কাছেরটি ব্যবহার LAST_VALUEকরে ORDER BYযা যা কাজ করছে না তা অগ্রাহ্য করার পরে আমার অর্ডার করা সর্বশেষ নন-মান প্রয়োজন।

SELECT DISTINCT 
        cat, 
        LAST_VALUE(val1) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val1,
        LAST_VALUE(val2) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val2
FROM    #tab
cat  val1 val2
A    NULL NULL
B    10   NULL

প্রকৃত টেবিলটিতে cat(তারিখ এবং স্ট্রিং কলাম) এর জন্য আরও কলাম এবং সর্বশেষ নন-মানটি নির্বাচন করতে আরও ভাল কলাম (তারিখ, স্ট্রিং এবং সংখ্যা কলাম) রয়েছে।

এই নির্বাচনটি কীভাবে করা যায় সে সম্পর্কে কোনও ধারণা।


1
@ Vérace গোষ্ঠীবদ্ধে দ্বারা catদ্বারা আদেশ t
এডমন্ড

1
@ ypercubeᵀᴹ না, কোনও অনুপস্থিত Q4 মান নেই, tমানগুলি পুনরাবৃত্তি করে। এটি ভাল আচরণ করা ডেটা নয়।
এডমন্ড

4
ঠিক আছে তবে সেক্ষেত্রে আপনাকে একটি অর্ডার সরবরাহ করতে হবে যা একটি নিখুঁত ক্রম নির্ধারণ করে। PARTITION BY cat ORDER BY t, idউদাহরণ স্বরূপ. অন্যথায়, একই ক্যোয়ারী (যে কোনও প্রশ্নের) আপনাকে পৃথক মৃত্যুদণ্ড কার্যকর করার ক্ষেত্রে বিভিন্ন ফলাফল দিতে পারে। যদি টেবিলের কলামগুলি কেবলমাত্র আপনিই দেখান তবে আমি দেখতে পাই না তবে কীভাবে আমরা একটি নির্ধারিত আদেশ পেতে পারি!
ypercubeᵀᴹ

1
@ ইয়পারকিউবᵀᴹ এতে চ্যালেঞ্জ রয়েছে। ডেটাতে কোনও আইডি কলাম নেই। এখানে একাধিক গ্রুপিং কলাম রয়েছে, একটি স্ট্রিং কলাম যা গোষ্ঠী ক্রমের মধ্যে ব্যবহার করা যেতে পারে এবং তারপরে নালগুলি ছেদ করে একাধিক মান কলামগুলি।
এডমন্ড

1
যদি আপনি এসকিউএল সার্ভারকে নির্ধারণ করে বলতে না পারেন যে সারিগুলির সারণিটি কীভাবে হওয়া উচিত, তবে এই ডেটার কোনও গ্রাহক কীভাবে পার্থক্যটি জানতে পারবেন?
অ্যারন বারট্র্যান্ড

উত্তর:


10

ইটজিক বেন গানের দ্য লাস্ট অ ননুলল ধাঁধা থেকে কনকাটেশন কৌশলটি ব্যবহার করা আপনার নমুনা সারণী এবং কলামের ডেটা ধরণের সাথে দেখতে এইরকম লাগবে।

select T.cat,
       cast(substring(
                     max(cast(T.t as binary(2)) + cast(T.val1 as binary(4))),
                     3,
                     4
                     ) as int),
       cast(substring(
                     max(cast(T.t as binary(2)) + cast(T.val2 as binary(1))),
                     3,
                     1
                     ) as char(1))
from #tab as T
group by T.cat;

এখানে চিত্র বর্ণনা লিখুন

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

with C1 as
(
  -- Concatenate the ordering column with the value column
  select T.cat,
        cast(T.t as binary(2)) + cast(T.val1 as binary(4)) as val1,
        cast(T.t as binary(2)) + cast(T.val2 as binary(1)) as val2
  from #tab as T
),
C2 as
(
  -- Get the max concatenated value per group
  select C1.cat,
         max(C1.val1) as val1,
         max(C1.val2) as val2
  from C1
  group by C1.cat
)
-- Extract the value from the concatenated column
select C2.cat,
       cast(substring(C2.val1, 3, 4) as int) as val1,
       cast(substring(C2.val2, 3, 1) as char(1)) as val2
from C2;

এই সমাধানটি এমন সত্যটি ব্যবহার করে যে কোনও জিনিসের সাথে নাল মানকে একত্রিত করে নাল মান হয়। সেট কনকনাT_NULL_YIELDS_NULL (লেনদেন-এসকিউএল)


খুব ভাল পাতিত মিকায়েল। এই সমাধানটি আমাকে বেশ কয়েকবার বাঁচিয়েছে, যদিও আমি প্রথমে ইতজিকের নিবন্ধের শেষটি পেয়েছি। এতে তিনি এটিকে "পদক্ষেপ 2" হিসাবে লেবেল করেছিলেন যখন বাস্তবে এটি আরও 1 ধাপের পিছনে যুক্তি বাস্তবায়নের মতো ছিল
পিমব্রউবাররা

2

পার্টিশনটি করবে কেবল NUL এর জন্য একটি চেক যোগ করুন

SELECT DISTINCT 
        cat, 
        FIRST_VALUE(val1) OVER(PARTITION BY cat ORDER BY CASE WHEN val1 is NULL then 0 else 1 END DESC, t desc) AS val1,
        FIRST_VALUE(val2) OVER(PARTITION BY cat ORDER BY CASE WHEN val2 is NULL then 0 else 1 END DESC, t desc) AS val2
FROM    #tab

0

এটি করা উচিত। সারি_সংখ্যা () এবং একটি যোগদান

আপনার যদি ভাল সাজানো না থাকে তবে আপনাকে আশা করতে হবে Q3 এর মধ্যে একটিই নাল নয়।

declare @t TABLE (cat CHAR(1), t CHAR(2), val1 INT, val2 CHAR(1));
INSERT INTO @t VALUES 
    ('A','Q1',2,NULL),('A','Q2',NULL,'P'),('A','Q3',1,NULL),('A','Q3',NULL,NULL),
    ('B','Q1',5,NULL),('B','Q2',NULL,'P'),('B','Q3',NULL,'C'),('B','Q3',10,NULL);

--SELECT *
--     , row_number() over (partition by cat order by t) as rn
--FROM   @t
--where val1 is not null or val2 is not null;

select t1.cat, t1.val1, t2.val2 
from  ( SELECT t.cat, t.val1
             , row_number() over (partition by cat order by t desc) as rn
        FROM   @t t
        where val1 is not null 
       ) t1
join   ( SELECT t.cat, t.val2
             , row_number() over (partition by cat order by t desc) as rn
        FROM   @t t
        where val2 is not null 
       ) t2
   on t1.cat = t2.cat
  and t1.rn = 1
  and t2.rn = 1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.