عنوان:

‫دستکاری کردن عملیات Sort در SQL Server


نویسنده: فرهاد فرهمندخواه
تاریخ: ۱۳۹۱/۰۹/۱۴ ۰:۱۹
آدرس: www.dntips.ir
گاهی اوقات لازم می‌باشد، در زمان Sort نمودن یک ستون، تمایل داشته باشیم Range خاصی از مقادیر آن ستون در ابتدا قرار گیرد، و عملیات Sort پس از آن Range، اعمال گردد. برای انجام چنین کاری می‌توانیداز روش زیر استفاده نمایید:
برای درک مطلب مثالی می‌زنیم:
در ابتدا Script زیر را اجرا نمایید، که شامل یک جدول و درج چند رکورد در آن می‌باشد:
Create Table TestSort
(ID  int identity(1,1),
Name nvarchar(30),
Color nvarchar(15)
)
درج رکورد:
Insert into TestSort (Name,color)
Values  ('Adjustable Race',null)
       ,('Bearing Ball',null)
       ,('Headset Ball Bearings',null)
       ,('LL Crankarm','Black')
       ,('ML Crankarm','Black')
       ,('Chainring','Black')
       ,('Front Derailleur Cage','Silver')
       ,('Front Derailleur Linkage','Silver')
       ,('Lock Ring','Silver')
       ,('HL Road Frame - Red, 62','Red')
       ,('HL Road Frame - Red, 48','Red')
       ,('LL Road Frame - Red, 44','Red')
       ,('Full-Finger Gloves, M','RED')
       ,('Road-550-W Yellow, 38','Yellow')
       ,('Road-550-W Yellow, 40','Yellow')
       ,('Road-550-W Yellow, 42','Yellow')
       ,('Classic Vest, S','Blue')
       ,('Classic Vest, M','Blue')
       ,('Classic Vest, L','Blue')
در جدول TestSort ستونی به نام Color داریم، که نام رنگها در آن درج شده است، رنگهایی همچون  Black ، Silver،Blue،Yellow و Red
درابتدا روی ستون Color بصورت نرمال Sort صعودی انجام می‌دهیم:
Select t.ID,t.Name,t.Color from TestSort as t order by t.Color
خروجی:

مطابق شکل،زمانی که Sort بصورت صعودی است، رکوردهایی را که ستون Color آنها دارای مقدار Null می‌باشند، در ابتدای جدول قرار گرفته اند.
در ادامه می‌خواهیم، عملیات Sort ی را روی ستون Color انجام دهیم، بطوریکه تمامی رکوردهایی که مقدار ستون Color شان Red است، در ابتدای جدول قرار گیرد، و پس از آن عملیات سورت روی رنگهای دیگر اعمال شود.
برای انجام چنین کاری کافیست Script زیر را اجرا نمایید:
Select t.ID,t.Name,t.Color from TestSort as t 
Where t.color is not null
order by  Case t.Color
When 'Red' Then Null
Else t.color 
End;
خروجی:

چطور اینکار انجام شد:
اگر بهScript ذکر شده دقت نمایید، در قسمت Order by اشاره کردیم، تمام مقادیر Red در ستون Color به Null تغییر کنند، بنابراین SQL Server، در ابتدا مقادیر Red را یافته آنها را به Null تغییر و سپس عملیات سورت را انجام می‌دهد،
برای درک بیشتر عملیاتی را که SQL Server پشت صحنه انجام می‌دهد با Script  زیر قابل شبیه سازی میباشد:
Select * into Simulation from 
(Select t.ID,t.Name,t.Color,
Case t.Color
When 'Red' Then Null
Else t.color 
End RedNull
from TestSort as t 
Where t.color is not null) A
سپس روی ستون RedNull از جدول Simulation سورت انجام می‌دهیم:
Select * from Simulation order by Rednull
خروجی:

مطابق شکل،پشت صحنه SQL Server چنین کاری را انجام می‌دهد، و در زمان نمایش ستون RedNull پنهان یا حذف می‌گردد، و ستون Color، Name و ID نمایش داده می‌شود.
امیدوارم مفید واقع شده باشد.

نظرات

  • محمد سلیم آبادی در ۱۳۹۱/۱۰/۲۹ ۱۶:۲
    سلام،
    شما از اینکه مقادیر null هنگامی که مرتب سازی غیرنزولی است در ابتدا آمدند این برداشت را داشتین که مقادیر red را ابتدا به null تبدیل کنید... .
    اما من پیشنهاد دیگری دارم، با کمک اعداد به رنگ‌ها اولیت میدهیم سپس در اولیت‌های یکسان مرتب سازی بر اساس رنگ صورت می‌گیرد.
    یعنی:
    Select ID,t.Name,Color 
      from TestSort
     Where t.color is not null
     order by  case when color = 'red' then 0 else 1 end,
               color;



  • محمدحسین فخرآوری در ۱۳۹۸/۰۶/۱۳ ۷:۵۲
     با سلام
    SELECT * FROM (
    SELECT i.* FROM dbo.ProductInventory i
    )bb
     
     
    ORDER BY
    CASE WHEN @IdOrderList = 1 THEN bb.Inventory END DESC,
    CASE WHEN @IdOrderList = 2 THEN bb.TotalPrice END ASC,
    CASE WHEN @IdOrderList = 3 THEN bb.TotalPrice END DESC,
    CASE WHEN @IdOrderList = 4 THEN bb.Inventory END ASC,
     
     
    CASE WHEN @IdOrderList = 5 THEN bb.Inventory END DESC,
    CASE WHEN @IdOrderList = 5 THEN bb.TotalPrice END ASC,
     
     
    CASE WHEN @IdOrderList = 6 THEN bb.Inventory END DESC,
    CASE WHEN @IdOrderList = 6 THEN bb.TotalPrice END DESC
    در قسمت @IdOrderList با 5و6 میخواهم Inventory با TotalPrice با هم سورت شود.
    یعنی موجودی دار با قیمت زیاد
    موجودی دار با قیمت کم

    این کد میاد اول کلا Inventory بعد TotalPrice سورت میکنه همزمان این کار نمیکنه.   
    • محسن خان در ۱۳۹۸/۰۶/۱۳ ۸:۱۱
      CASE @IdOrderList WHEN 5 THEN bb.Inventory END DESC, bb.TotalPrice,
      CASE @IdOrderList WHEN 6 THEN bb.Inventory END DESC, bb.TotalPrice DESC
      • محمدحسین فخرآوری در ۱۳۹۸/۰۶/۱۳ ۸:۴۳
        با سلام یک خطا خوردم
        ORDER BY 
        CASE WHEN @IdOrderList = 1 THEN bb.Inventory END DESC,
        CASE WHEN @IdOrderList = 2 THEN bb.TotalPrice END ASC,
        CASE WHEN @IdOrderList = 3 THEN bb.TotalPrice END DESC,
        CASE WHEN @IdOrderList = 4 THEN bb.Inventory END ASC,
        
        CASE WHEN @IdOrderList = 5 THEN bb.Inventory END DESC,
        CASE WHEN @IdOrderList = 5 THEN bb.TotalPrice END ASC,
        
        --CASE WHEN @IdOrderList = 6 THEN bb.Inventory END DESC,
        --CASE WHEN @IdOrderList = 6 THEN bb.TotalPrice END DESC
        
        CASE @IdOrderList WHEN 5 THEN bb.Inventory END DESC, bb.TotalPrice,
        CASE @IdOrderList WHEN 6 THEN bb.Inventory END DESC, bb.TotalPrice DESC
        
        OFFSET (@PageIndex-1)*20 ROWS
        FETCH NEXT 20 ROWS ONLY
        A column has been specified more than once in the order by list. Columns in the order by list must be unique.