এসকিউএল সার্ভার 2005-এ নূন্যতম একাধিক কলাম পাওয়ার সবচেয়ে কার্যকর উপায় কী?


29

আমি এমন পরিস্থিতিতে আছি যেখানে আমি 6 টি কলামের ন্যূনতম মান পেতে চাই।

এটি সম্পাদন করার জন্য আমি এখনও তিনটি উপায় পেয়েছি, তবে এই পদ্ধতির পারফরম্যান্স নিয়ে আমার উদ্বেগ রয়েছে এবং এটি জানতে চাই যে পারফরম্যান্সের জন্য আরও ভাল be

প্রথম পদ্ধতিটি হ'ল বড় কেস স্টেটমেন্ট ব্যবহার করা । উপরের লিঙ্কটিতে উদাহরণের ভিত্তিতে 3 টি কলাম সহ এখানে একটি উদাহরণ রয়েছে। আমার কেস স্টেটমেন্টটি অনেক দীর্ঘ হতে পারে যেহেতু আমি 6 টি কলাম দেখছি।

Select Id,
       Case When Col1 <= Col2 And Col1 <= Col3 Then Col1
            When Col2 <= Col3 Then Col2 
            Else Col3
            End As TheMin
From   MyTable

দ্বিতীয় বিকল্পটি হ'ল UNIONএকাধিক সিলেক্ট স্টেটমেন্ট সহ অপারেটরটি ব্যবহার করা । আমি এটি এমন কোনও ইউডিএফের মধ্যে রাখব যা কোনও আইডি প্যারামিটার গ্রহণ করে।

select Id, dbo.GetMinimumFromMyTable(Id)
from MyTable

এবং

select min(col)
from
(
    select col1 [col] from MyTable where Id = @id
    union all
    select col2 from MyTable where Id = @id
    union all
    select col3 from MyTable where Id = @id
) as t

এবং তৃতীয় বিকল্পটি আমি খুঁজে পেয়েছি হ'ল ইউএনপিআইভিটি অপারেটরটি ব্যবহার করা , যা আমি এখনও অবধি জানতাম না

with cte (ID, Col1, Col2, Col3)
as
(
    select ID, Col1, Col2, Col3
    from TestTable
)
select cte.ID, Col1, Col2, Col3, TheMin from cte
join
(
    select
        ID, min(Amount) as TheMin
    from 
        cte 
        UNPIVOT (Amount for AmountCol in (Col1, Col2, Col3)) as unpvt
    group by ID
) as minValues
on cte.ID = minValues.ID

টেবিলের আকার এবং ফ্রিকোয়েন্সি যার কারণে এই টেবিলটি অনুসন্ধান করা এবং আপডেট করা হয়েছে, এই প্রশ্নাগুলি ডেটাবেজে যে প্রভাব ফেলবে তা নিয়ে আমি উদ্বিগ্ন।

এই কোয়েরিটি কয়েক মিলিয়ন রেকর্ড সহ একটি টেবিলের সাথে যুক্ত হওয়ার জন্য ব্যবহৃত হবে, তবে যে রেকর্ডগুলি দেওয়া হয়েছিল তা একবারে কমিয়ে প্রায় একশ রেকর্ড হয়ে যাবে। এটি সারা দিন অনেকবার চলবে এবং আমি যে 6 টি কলাম জিজ্ঞাসা করছি তা প্রায়শই আপডেট হয় (সেগুলিতে প্রতিদিনের পরিসংখ্যান রয়েছে)। আমি মনে করি না যে আমি জিজ্ঞাসা করছি 6 টি কলামে কোনও সূচক রয়েছে।

সর্বনিম্ন একাধিক কলাম পাওয়ার চেষ্টা করার সময় এই পদ্ধতিগুলির মধ্যে কোনটি কার্যকারণের জন্য ভাল? বা এর চেয়ে আরও ভাল কোন পদ্ধতি আছে যা আমি জানি না?

আমি এসকিউএল সার্ভার 2005 ব্যবহার করছি

নমুনা ডেটা ও ফলাফল

যদি আমার ডেটাতে এই জাতীয় রেকর্ড থাকে:

আইডি কল 1 কল 2 কল 3 কল 4 কল 5 কল 6
1 3 4 0 2 1 5
2 2 6 10 5 7 9
3 1 1 2 3 4 5
4 9 5 4 6 8 9

শেষ ফলাফল হওয়া উচিত

আইডির মান
1 0
2 2
3 1
4 4

উত্তর:


22

আমি সমস্ত 3 টি পদ্ধতির কর্মক্ষমতা পরীক্ষা করেছি এবং আমি যা পেয়েছি তা এখানে:

  • 1 রেকর্ড: কোন পার্থক্য লক্ষ্য করা যায় না
  • 10 রেকর্ড: কোন লক্ষণীয় পার্থক্য
  • 1,000 রেকর্ডস: কোন লক্ষণীয় পার্থক্য
  • 10,000 রেকর্ডস: UNIONসাবকিরিটি একটু ধীর ছিল। CASE WHENক্যোয়ারী একটু চেয়ে দ্রুত UNPIVOTকরুন।
  • ১০০,০০০ রেকর্ডস: UNIONসাবকিউরিটি উল্লেখযোগ্যভাবে ধীর, তবে UNPIVOTক্যোয়ারীর চেয়ে CASE WHENক্যোয়ারীটি একটু দ্রুত হয়ে যায়
  • 500,000 রেকর্ডস: UNIONsubquery এখনও উল্লেখযোগ্যভাবে ধীর, কিন্তু কোয়েরির UNPIVOTচেয়ে অনেক দ্রুত হয়ে ওঠেCASE WHEN

সুতরাং শেষ ফলাফল বলে মনে হচ্ছে

  • ছোট রেকর্ড সেট রয়েছে বলে মনে হয় না যে এটির পক্ষে কোনও পার্থক্য যথেষ্ট। পড়তে এবং বজায় রাখতে সবচেয়ে সহজ যা ব্যবহার করুন।

  • একবার আপনি বড় আকারের রেকর্ড সেটগুলিতে প্রবেশ শুরু করলে, UNION ALLসাবকিউরিটি অন্য দুটি পদ্ধতির তুলনায় খারাপ অভিনয় করতে শুরু করে।

  • CASEবিবৃতি সঞ্চালিত একটি নির্দিষ্ট বিন্দু পর্যন্ত সেরা আপ (আমার ক্ষেত্রে প্রায় 100 কিলোবাইট সারি), এবং যা বাতলান UNPIVOTক্যোয়ারী সেরা-পারফর্মিং ক্যোয়ারী হয়ে

আপনার ক্যালিফোর্নিয়ার স্ক্রিন, ডেটা এবং বর্তমান সার্ভার লোডের ফলস্বরূপ সম্ভবত একটি ক্যোয়ারী আরও ভাল হয়ে উঠবে সম্ভবত আপনার নিজের সিস্টেমের সাথে পরীক্ষা করার বিষয়টি নিশ্চিত হন।

আমি মিকেলের উত্তরটি ব্যবহার করে কিছু পরীক্ষাও চালিয়েছি ; তবে বেশিরভাগ রেকর্ডসেট আকারের জন্য এখানে চেষ্টা করা অন্যান্য 3 টি পদ্ধতির চেয়ে ধীর ছিল। কেবলমাত্র ব্যতিক্রমটি ছিল এটি UNION ALLখুব বড় রেকর্ডসেট আকারের ক্যোয়ারির চেয়ে ভাল did আমি এটি পছন্দ করি যদিও এটি ক্ষুদ্রতম মান ছাড়াও কলামের নামটি দেখায়।

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


6

দ্রুত কোনটি সম্পর্কে জানেন না তবে আপনি এরকম কিছু চেষ্টা করতে পারেন।

declare @T table
(
  Col1 int,
  Col2 int,
  Col3 int,
  Col4 int,
  Col5 int,
  Col6 int
)

insert into @T values(1, 2, 3, 4, 5, 6)
insert into @T values(2, 3, 1, 4, 5, 6)

select T4.ColName, T4.ColValue
from @T as T1
  cross apply (
                select T3.ColValue, T3.ColName
                from (
                       select row_number() over(order by T2.ColValue) as rn,
                              T2.ColValue,
                              T2.ColName
                       from (
                              select T1.Col1, 'Col1' union all
                              select T1.Col2, 'Col2' union all
                              select T1.Col3, 'Col3' union all
                              select T1.Col4, 'Col4' union all
                              select T1.Col5, 'Col5' union all
                              select T1.Col6, 'Col6'
                            ) as T2(ColValue, ColName)
                     ) as T3
                where T3.rn = 1
              ) as T4

ফলাফল:

ColName ColValue
------- -----------
Col1    1
Col3    1

কোন স্তম্ভের ন্যূনতম মান রয়েছে তা আপনি যদি আগ্রহী না হন তবে পরিবর্তে আপনি এটি ব্যবহার করতে পারেন।

declare @T table
(
  Id int,
  Col1 int,
  Col2 int,
  Col3 int,
  Col4 int,
  Col5 int,
  Col6 int
)

insert into @T
select 1,        3,       4,       0,       2,       1,       5 union all
select 2,        2,       6,      10,       5,       7,       9 union all
select 3,        1,       1,       2,       3,       4,       5 union all
select 4,        9,       5,       4,       6,       8,       9

select T.Id, (select min(T1.ColValue)
              from (
                      select T.Col1 union all
                      select T.Col2 union all
                      select T.Col3 union all
                      select T.Col4 union all
                      select T.Col5 union all
                      select T.Col6
                    ) as T1(ColValue)
             ) as ColValue
from @T as T

একটি সরলীকৃত আনবিভট ক্যোয়ারী।

select Id, min(ColValue) as ColValue
from @T
unpivot (ColValue for Col in (Col1, Col2, Col3, Col4, Col5, Col6)) as U
group by Id

6

CASEআপনার প্রয়োজন যুক্তিযুক্ত করতে একটি বিবৃতি ব্যবহার করে একটি স্থির গণিত কলাম যুক্ত করুন ।

ন্যূনতম মানটি তখন সর্বদা কার্যকরভাবে উপলব্ধ হবে যখন আপনাকে সেই মানটির উপর ভিত্তি করে একটি যোগ (বা অন্য যে কোনও কিছু) করতে হবে।

উত্সের মানগুলির কোনও পরিবর্তন ( INSERT/ UPDATE/ MERGE) প্রতিবার মানটি পুনঃসংযুক্ত করা হবে । আমি বলছি না এই অগত্যা কাজের চাপ জন্য সবচেয়ে ভালো সমাধান, আমি নিছক যেমন অফার একটি , সমাধান শুধু অন্যান্য উত্তর চাই। কাজের চাপের জন্য কোনটি সেরা তা কেবল ওপি নির্ধারণ করতে পারে।


1

6 তারিখের জন্য কেস স্টেটমেন্ট। কম কাজ করার জন্য, প্রথম কেস স্টেটমেন্ট থেকে সত্য শাখাটি অনুলিপি করুন। সবচেয়ে খারাপ ক্ষেত্রে হ'ল ডেট 1 সর্বনিম্ন মান হয়, ডেট 6 যখন সর্বনিম্ন মান হয় তবে সবচেয়ে ভাল কেস হয়, তাই ডেট 6-এ সর্বাধিক সম্ভাব্য তারিখটি রাখুন। গণিত কলামগুলির সীমাবদ্ধতার কারণে আমি এটি লিখেছিলাম।

CASE WHEN Date1 IS NULL OR Date1 > Date2 THEN
        CASE WHEN Date2 IS NULL OR Date2 > Date3 THEN
            CASE WHEN Date3 IS NULL OR Date3 > Date4 THEN
                CASE WHEN Date4 IS NULL OR Date4 > Date5 THEN
                    CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                        Date6
                    ELSE
                        Date5
                    END
                ELSE
                    CASE WHEN Date4 IS NULL OR Date4 > Date6 THEN
                        Date6
                    ELSE
                        Date4
                    END
                END
            ELSE
                CASE WHEN Date3 IS NULL OR Date3 > Date5 THEN
                    CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                        Date6
                    ELSE
                        Date5
                    END
                ELSE
                    CASE WHEN Date3 IS NULL OR Date3 > Date6 THEN
                        Date6
                    ELSE
                        Date3
                    END
                END
            END
        ELSE
            CASE WHEN Date2 IS NULL OR Date2 > Date4 THEN
                CASE WHEN Date4 IS NULL OR Date4 > Date5 THEN
                    CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                        Date6
                    ELSE
                        Date5
                    END
                ELSE
                    CASE WHEN Date4 IS NULL OR Date4 > Date5 THEN
                        CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                            Date6
                        ELSE
                            Date5
                        END
                    ELSE
                        CASE WHEN Date4 IS NULL OR Date4 > Date6 THEN
                            Date6
                        ELSE
                            Date4
                        END
                    END
                END
            ELSE
                CASE WHEN Date2 IS NULL OR Date2 > Date5 THEN
                    CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                        Date6
                    ELSE
                        Date5
                    END
                ELSE
                    CASE WHEN Date2 IS NULL OR Date2 > Date6 THEN
                        Date6
                    ELSE
                        Date2
                    END
                END
            END
        END
ELSE
    CASE WHEN Date1 IS NULL OR Date1 > Date3 THEN
        CASE WHEN Date3 IS NULL OR Date3 > Date4 THEN
            CASE WHEN Date4 IS NULL OR Date4 > Date5 THEN
                CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                    Date6
                ELSE
                    Date5
                END
            ELSE
                CASE WHEN Date4 IS NULL OR Date4 > Date6 THEN
                    Date6
                ELSE
                    Date4
                END
            END
        ELSE
            CASE WHEN Date3 IS NULL OR Date3 > Date5 THEN
                CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                    Date6
                ELSE
                    Date5
                END
            ELSE
                CASE WHEN Date3 IS NULL OR Date3 > Date6 THEN
                    Date6
                ELSE
                    Date3
                END
            END
        END
    ELSE
        CASE WHEN Date1 IS NULL OR Date1 > Date4 THEN
            CASE WHEN Date4 IS NULL OR Date4 > Date5 THEN
                CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                    Date6
                ELSE
                    Date5
                END
            ELSE
                CASE WHEN Date4 IS NULL OR Date4 > Date6 THEN
                    Date6
                ELSE
                    Date4
                END
            END
        ELSE
            CASE WHEN Date1 IS NULL OR Date1 > Date5 THEN
                CASE WHEN Date5 IS NULL OR Date5 > Date6 THEN
                    Date6
                ELSE
                    Date5
                END
            ELSE
                CASE WHEN Date1 IS NULL OR Date1 > Date6 THEN
                    Date6
                ELSE
                    Date1
                END
            END
        END
    END
END

আপনি যদি এই পৃষ্ঠাটি জুড়ে খালি তারিখের তুলনা করতে গিয়ে দেখেন এবং পারফরম্যান্স বা সামঞ্জস্যতা সম্পর্কে উদ্বিগ্ন না হন তবে আপনি একটি সারণী মান নির্মাতা ব্যবহার করতে পারেন, যা সাব-সাবলেটিকদের অনুমতিপ্রাপ্ত যেখানেই ব্যবহার করা যেতে পারে (এসকিউএল সার্ভার ২০০৮ এবং তার বেশি):

Lowest =    
(
    SELECT MIN(TVC.d) 
    FROM 
    (
        VALUES
            (Date1), 
            (Date2), 
            (Date3), 
            (Date4), 
            (Date5), 
            (Date6)
    ) 
    AS TVC(d)
)

1

আপনার caseবক্তব্য দক্ষ নয়। আপনি সবচেয়ে খারাপ ক্ষেত্রে 5 টি তুলনা করছেন, এবং সেরা ক্ষেত্রে 2; যদিও nসর্বাধিক n-1তুলনা করা উচিত সর্বনিম্ন সন্ধান করা ।

প্রতিটি সারির জন্য, আপনি 2 এর পরিবর্তে 3.5 টি তুলনা করছেন Thus সুতরাং এটি আরও সিপিইউ সময় নিচ্ছে এবং ধীর। নীচের caseবিবৃতিটি ব্যবহার করে আবার আপনার পরীক্ষা করে দেখুন । এটা ঠিক সারি প্রতি 2 তুলনা ব্যবহার করছে ও অধিক কার্যকরী হওয়া উচিত unpivotএবং union all

Select Id, 
       Case 
           When Col1 <= Col2 then case when Col1 <= Col3 Then Col1  else col3 end
            When  Col2 <= Col3 Then Col2  
            Else Col3 
            End As TheMin 
From   YourTableNameHere

union allহিসাবে আপনি সারি প্রতি কিন্তু পুরো টেবিল জন্য নয় সর্বনিম্ন মান পাচ্ছেন পদ্ধতি আপনার ক্ষেত্রে ভুল। এছাড়াও, আপনি একই টেবিলটি 3 বার স্ক্যান করতে যাচ্ছেন বলে এটি দক্ষ হবে না। যখন টেবিলটি ছোট হয়, আই / ও খুব বেশি পার্থক্য রাখে না, তবে বড় টেবিলের জন্য এটি হয়ে যাবে। সেই পদ্ধতিটি ব্যবহার করবেন না।

Unpivotভাল এবং আপনার টেবিলে ক্রস যুক্ত করে ম্যানুয়াল আনপিবটকে পাশাপাশি চেষ্টা করার চেষ্টা করুন (select 1 union all select 2 union all select 3)। এটি হিসাবে দক্ষ হতে হবে unpivot

আপনার কাছে জায়গার সমস্যা না থাকলে সেরা সমাধানের একটি গণিত স্থায়ী কলাম থাকবে। এটি 4 বাইট দ্বারা সারিটির আকার যুক্ত করবে (আমি মনে করি আপনার intটাইপ হবে ), যা ফলস্বরূপ সারণির আকার বাড়িয়ে তুলবে।

যাইহোক, আপনার সিস্টেমে স্পেস এবং মেমরি ইস্যু এবং সিপিইউ তখন এটি স্থির রাখবে না তবে কেস স্টেটমেন্টটি ব্যবহার করে সাধারণ গণিত কলাম ব্যবহার করুন। এটি কোডটিকে সহজতর করবে।


-1

আমি অনুমান করি যে প্রথম বিকল্পটি দ্রুততম (যদিও এটি প্রোগ্রামিং দৃষ্টিকোণ থেকে খুব স্পষ্ট দেখাচ্ছে না)। এটি হ'ল এন সারিগুলির সাথে ডিল করে (যেখানে এন টেবিলের আকার) এবং কোনও পদ্ধতি বা 2 বা 3 এর মতো বাছাই করতে হবে না।

বড় নমুনা সহ একটি পরীক্ষা পয়েন্ট প্রমাণ করতে হবে।

এখনও বিবেচনা করার মতো অন্য বিকল্পটি (যেন আপনার আরও প্রয়োজন!) হ'ল আপনার টেবিলের উপরে একটি বস্তুগত দৃষ্টি তৈরি করা । যদি আপনার টেবিলের আকারটি কয়েকশো হাজার বা তারও বেশি হয়। এইভাবে, সারি পরিবর্তিত হওয়ার সময় ন্যূনতম মানটি গণনা করা হয় এবং প্রতিটি সন্ধানের সাথে পুরো টেবিলটি প্রক্রিয়া করতে হবে না। এসকিউএল সার্ভারে, বস্তুগত দর্শনগুলি ইনডেক্সড ভিউ বলে


-1
Create table #temp
   (
    id int identity(1,1),
    Name varchar(30),
    Year1 int,
    Year2 int,
    Year3 int,
    Year4 int
   )

   Insert into #temp values ('A' ,2015,2016,2014,2010)
   Insert into #temp values ('B' ,2016,2013,2017,2018)
   Insert into #temp values ('C' ,2010,2016,2014,2017)
   Insert into #temp values ('D' ,2017,2016,2014,2015)
   Insert into #temp values ('E' ,2016,2016,2016,2016)
   Insert into #temp values ('F' ,2016,2017,2018,2019)
   Insert into #temp values ('G' ,2016,2017,2020,2019)

   Select *, Case 
                 when Year1 >= Year2 and Year1 >= Year3 and Year1 >= Year4 then Year1
                 when Year2 >= Year3 and Year2 >= Year4 and Year2 >= Year1 then Year2
                 when Year3 >= Year4 and Year3 >= Year1 and Year3 >= Year2 then Year3
                 when Year4 >= Year1 and Year4 >= Year2 and Year4 >= Year3 then Year4  
                 else Year1 end as maxscore  
                 from #temp

আপনি NULLs এর জন্য অ্যাকাউন্টিং করছেন না - এটি আপনার CASE এক্সপ্রেশনটিকে তুলনামূলকভাবে সহজ করে তোলে। তবে, যদি কমপক্ষে কোনও কলামের সত্যই নুল হয় তবে আপনার সমাধান Year1ফলাফল হিসাবে ফিরে আসবে , যা অগত্যা সঠিক হতে পারে না।
অ্যান্ড্রি এম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.