اشتراک‌ها
مجموعه ای روان برای یادگیری AngularCLI
https://github.com/Vintharas/angular2-step-by-step-01-your-first-component
https://github.com/Vintharas/angular2-step-by-step-02-refactoring-to-services
https://github.com/Vintharas/angular2-step-by-step-03-your-second-component-and-data-bindings
https://github.com/Vintharas/angular2-step-by-step-04-routing
https://github.com/Vintharas/angular2-step-by-step-05-forms-and-validation
https://github.com/Vintharas/angular2-step-by-step-06-consuming-real-data-with-http
مجموعه ای روان برای یادگیری AngularCLI
مطالب دوره‌ها
تهیه کوئری بر روی ایندکس‌های Full Text Search
در دو قسمت قبل ابتدا سیستم FTS را نصب و فعال کردیم و سپس تعدادی رکورد را ثبت کرده، کاتالوگ‌های FTS، ایندکس‌ها و Stop words متناظری را ایجاد کردیم. در این قسمت قصد داریم از این اطلاعات ویژه، استفاده کرده و کوئری بگیریم. مواردی که بررسی خواهند شد اصطلاحا Predicates نام داشته و شامل توابع مخصوصی مانند Contains و Freetext می‌شوند.


با استفاده از Contains predicate چه اطلاعاتی را می‌توان جستجو کرد؟

متد Contains مخصوص FTS، قابلیت یافتن کلمات و عبارات، تطابق کامل با عبارت در حال جستجو و یا حتی جستجوهای فازی را دارد. همچنین حالات مختلف صرفی یا inflectional یک کلمه را نیز می‌تواند جستجو کند (مانند jump، jumps و jumped). البته این مورد وابسته است به زبانی که در حین ایجاد ایندکس مشخص می‌شود. امکان یافتن کلماتی نزدیک و مشابه به کلماتی دیگر نیز پیش بینی شده‌است. پیشوندها و پسوندها را نیز می‌توان جستجو کرد. امکان تعیین وزن و اهمیت کلمات در حال جستجو وجود دارند (برای مثال در این جستجوی خاص، کلمه‌ی ویژه اهمیت بیشتری نسبت به بقیه دارد). متد Contains امکان جستجوی Synonyms را نیز دارد. برای مثال یافتن رکوردهایی که معنایی مشابه need دارند اما دقیقا حاوی کلمه‌ی need نیستند.


بررسی ریز جزئیات توانمندی‌های Contains predicate

1) جستجوی کلمات ساده
 -- Simple term
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'data');
در این کوئری که بر روی جدول Documents قسمت قبل انجام می‌شود، به دنبال عین واژه‌ی در حال جستجو هستیم.
باید دقت داشت که این نوع کوئری‌ها، حساس به حروف کوچک و بزرگ نیستند.
همچنین عبارت وارد شده از نوع یونیکد است. به همین جهت برای جلوگیری از تغییر encoding رشته وارد شده (و تفسیر آن بر اساس Collation بانک اطلاعاتی)، یک N به ابتدای عبارت افزوده شده‌است.

2) جستجوی عبارات
 -- Simple term - phrase
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'"data warehouse"');
اگر نیاز به یافتن عین عبارتی که از چند کلمه تشکیل شده‌است می‌باشد، نیاز است آن‌را با "" محصور کرد.

3) استفاده از عملگرهای منطقی مانند OR و AND
 -- Simple terms with logical OR
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'data OR index');
در این کوئری نحوه‌ی استفاده از عملگر منطقی OR را مشاهده می‌کنید.
و یا نحوه‌ی بکارگیری AND NOT در کوئری ذیل مشخص شده‌است:
 -- Simple terms with logical AND NOT
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'data AND NOT mining');
در این کوئری به دنبال رکوردهایی هستیم که docexcerpt آن‌ها دارای کلمه‌ی data بوده، اما شامل mining نمی‌شوند.
به علاوه با استفاده از پرانتزها می‌توان تقدم و تاخر عملگرهای منطقی را بهتر مشخص کرد:
 -- Simple terms with mny logical operators, order defined with parentheses
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'data OR (fact AND warehouse)');

4) جستجوی پیشوندها
 -- Prefix
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'"add*"');
در کوئری فوق به دنبال رکوردهایی هستیم که docexcerpt آن‌ها با کلمه‌ی add شروع می‌شوند. در این حالت نیز استفاده از "" اجباری است. اگر از "" استفاده نشود، FTS به دنبال تطابق عینی با عبارت وارد شده خواهد گشت.

5) جستجوهای Proximity

Proximity در اینجا به معنای یافتن واژه‌هایی هستند که نزدیک (از لحاظ تعداد فاصله بر حسب کلمات) به واژه‌ای دیگر می‌باشند.
 -- Simple proximity
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'NEAR(problem, data)');
برای این منظور از واژه‌ی NEAR استفاده می‌شود؛ به همراه ذکر دو واژه‌ای که به دنبال آن‌ها هستیم. معنای کوئری فوق این است: رکوردهایی را پیدا کن که در آن در یک جایی از خلاصه سند، کلمه‌ی problem وجود دارد و در جایی دیگر از آن خلاصه‌ی سند، کلمه‌ی data.
همچنین می‌توان مشخص کرد که این نزدیک بودن دقیقا به چه معنایی است:
 -- Proximity with max distance 5 words
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'NEAR((problem, data),5)');

-- Proximity with max distance 1 word
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'NEAR((problem, data),1)');
در این کوئری‌ها اعداد 1 و 5، بیانگر فاصله‌ی بین دو کلمه‌‌ای هستند (فاصله بر اساس تعداد کلمه) که قرار است در نتایج جستجو حضور داشته باشند. مقدار پیش فرض آن Max است؛ یعنی در هر جایی از سند.
همچنین می‌توان مشخص کرد که ترتیب جستجو باید دقیقا بر اساس نحوه‌ی تعریف این کلمات در کوئری باشد:
 -- Proximity with max distance and order
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'NEAR((problem, data),5, TRUE)');
GO
پارامتر آخر یا flag، به صورت پیش فرض false است. به این معنا که ترتیب این دو کلمه در جستجو اهمیتی ندارند.

6) جستجوی بر روی بیش از یک فیلد
در قسمت قبل، FULLTEXT INDEX انتهای بحث را بر روی دو فیلد docexcerpt و doccontent تهیه کردیم. اگر نیاز باشد تا جستجوی انجام شده هر دو فیلد را شامل شود می‌توان به نحو ذیل عمل کرد:
 SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS((docexcerpt,doccontent), N'data');
در این حالت تنها کافی است دو فیلد را داخل یک پرانتز قرار داد.

یک نکته: اگر تعداد ستون‌های ایندکس شده زیاد است و نیاز داریم تا بر روی تمام آن‌ها FTS انجام شود، تنها کافی است پارامتر اول متد Contains را * وارد کنیم. * در اینجا به معنای تمام ستون‌هایی است که در حین تشکیل FULLTEXT INDEX ذکر شده‌اند.

7) جستجوهای صرفی یا inflectional
FTS بر اساس زبان انتخابی، در حین تشکیل ایندکس‌های خاص خودش، یک سری آنالیزهای دستوری را نیز بر روی واژه‌ها انجام می‌دهد. همچنین امکان تعریف زبان مورد استفاده در حین استفاده از متد Contains نیز وجود دارد.
 -- Inflectional forms

-- The next query does not return any rows
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'presentation');

-- The next query returns a row
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'FORMSOF(INFLECTIONAL, presentation)');
GO
در این مثال در کوئری اول به دنبال عین واژه‌ی وارد شده هستیم که با توجه به تنظیمات قسمت قبل و داده‌های موجود، خروجی را به همراه ندارد.
اکنون اگر کوئری دوم را که از FORMSOF جهت تعیین روش INFLECTIONAL استفاده کرده است، اجرا کنیم، به یک رکورد خواهیم رسید که در آن جمع واژه‌ی presentation وجود دارد.


8) جستجو برای یافتن متشابهات

برای نمونه اگر SQL Server 2012 بر روی سیستم شما نصب باشد، محل نصب واژه‌نامه‌های Synonyms یا واژه‌هایی همانند از لحاظ معنایی را در مسیر زیر می‌توانید مشاهده کنید:
 C:\...\MSSQL11.MSSQLSERVER\MSSQL\FTData
این‌ها یک سری فایل XML هستند با ساختار ذیل:
<XML ID="Microsoft Search Thesaurus">
    <thesaurus xmlns="x-schema:tsSchema.xml">
<diacritics_sensitive>0</diacritics_sensitive>
        <expansion>
            <sub>Internet Explorer</sub>
            <sub>IE</sub>
            <sub>IE5</sub>
        </expansion>
        <replacement>
            <pat>NT5</pat>
            <pat>W2K</pat>
            <sub>Windows 2000</sub>
        </replacement>
        <expansion>
            <sub>run</sub>
            <sub>jog</sub>
        </expansion>
        <expansion>
            <sub>need</sub>
            <sub>necessity</sub>
        </expansion>
    </thesaurus>
</XML>
در اینجا diacritics_sensitive به معنای حساسیت به لهجه است که به صورت پیش فرض برای تمام زبان‌ها خاموش است. سپس یک سری expansion و replacement را مشاهده می‌کنید.
فایل tsenu.xml به صورت پیش فرض برای زبان انگلیسی آمریکایی مورد استفاده قرار می‌گیرد. اگر محتویات آن‌را برای مثال با محتویات XML ایی فوق جایگزین کنید (در حین ذخیره باید دقت داشت که encoding فایل نیاز است Unicode باشد)، سپس باید SQL Server را از این تغییر نیز مطلع نمائیم:
 -- Load the US English file
EXEC sys.sp_fulltext_load_thesaurus_file 1033;
GO
 عدد 1033، عدد استاندارد زبان US EN است.
 البته اگر اینکار را انجام ندهیم، به صورت خودکار، اولین کوئری که از THESAURUS انگلیسی استفاده می‌کند، سبب بارگذاری آن خواهد شد.
 -- Synonyms

-- The next query does not return any rows
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'need');

-- The next query returns a row
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(docexcerpt, N'FORMSOF(THESAURUS, need)');
GO
در اولین مثال به دنبال عین واژه‌ی need در رکوردهای موجود هستیم که خروجی را بر نمی‌گرداند.
در ادامه اگر کوئری دوم را که از FORMSOF جهت تعیین روش THESAURUS استفاده کرده است، اجرا کنیم، به یک رکورد خواهیم رسید که در آن واژه‌ی necessity به کمک محتویات فایل tsenu.xml که پیشتر تهیه کردیم، بجای need وجود دارد.

9) جستجو بر روی خواص و متادیتای فایل‌ها
 -- Document properties
SELECT id, title, docexcerpt
FROM dbo.Documents
WHERE CONTAINS(PROPERTY(doccontent,N'Authors'), N'Test');
در اینجا نحوه‌ی جستجوی خواص فایل‌های docx ذخیره شده در قسمت قبل را مشاهده می‌کنید که شامل ذکر PROPERTY و ستون FTS مورد نظر است، به همراه نام خاصیت و عبارت جستجو.


کار با FREETEXT
 -- FREETEXT
SELECT *
FROM dbo.Documents
WHERE FREETEXT(docexcerpt, N'data presentation need');
FREETEXT عموما ردیف‌های بیشتری را نسبت به Contains بر می‌گرداند؛ چون جستجوی عمومی‌تری را انجام می‌دهد. در اینجا جستجو بر روی معنای عبارات انجام می‌شود و نه صرفا یافتن عباراتی دقیقا همانند عبارت در حال جستجو. در اینجا مباحث Synonyms و Inflectional ایی که پیشتر یاد شد، به صورت خودکار اعمال می‌شوند.
در کوئری فوق، کلیه رکوردهایی که با سه کلمه‌ی وارد شده (به صورت مجزا) به نحوی تطابق داشته باشند (تطابق کامل یا بر اساس تطابق‌های معنایی یا دستوری) باز گردانده خواهند شد. 
نظرات مطالب
نگاهی به درون سیستم Binding در WPF و یافتن مواردی که هنوز در حافظه‌اند
سلام،
می‌خواستم بدونم به چه شکل میتوانم متوجه شوم کدام قسمت از برنامه من موجب افزایش مصرف رم شده است؟ برای مثال برنامه من بعد گذشت 1 دقیقه از اجرای آن مصرف رم معادل 5MB دارم ولی پس از گذشت 10 دقیقه به 1GB میرسد.
نظرات مطالب
آشنایی با Window Function ها در SQL Server بخش دوم
سلام
من یه کوئری توسط Sum() Over() .. نوشتم که تو در تو هست که ترتیب جمع دستور بیرونی برام مهمه .
;WITH cteBed ([Counter], id_doc , [Year] ,id_Total , date_duc ,Number_Temp , number_fix , sumbed , sumbes , row_no ) AS (
SELECT [Counter], d.id_doc , d.[Year] ,r.id_Total , d.date_duc ,d.Number_Temp ,d.number_fix ,  
SUM( r.Mablagh_bed) OVER(PARTITION BY d.[Year] ,r.id_Total , d.Number_Temp) AS sumbed , 
 sumbes= 0,
ROW_NUMBER() OVER (PARTITION BY d.[Year] ,r.id_Total , d.date_duc , d.Number_Temp , d.number_fix  ORDER BY  d.date_duc )AS  row_no
FROM tbl_Records r JOIN tbl_Documents d ON d.id_doc = r.id_doc  ) ,
     
 cteBes ([Counter], id_doc , [Year] ,id_Total , date_duc ,Number_Temp , number_fix , sumbed , sumbes  , row_no) AS (
SELECT   [Counter], d.id_doc , d.[Year] ,r.id_Total , d.date_duc ,d.Number_Temp ,d.number_fix , sumbed = 0 , 
SUM( r.Mablagh_bes ) OVER(PARTITION BY d.[Year] ,r.id_Total , d.Number_Temp ) AS sumbes,
ROW_NUMBER() OVER (PARTITION BY d.[Year] ,r.id_Total ,  d.date_duc ,d.Number_Temp , d.number_fix ORDER BY  d.date_duc )AS row_no 
FROM tbl_Records r JOIN tbl_Documents d ON d.id_doc = r.id_doc ) 

SELECT [Counter], id_doc , [Year] ,id_Total , date_duc ,Number_Temp , number_fix , sumbed , sumbes , amountBed ,amountBes 
,SUM(amountBed)OVER(  ORDER BY [Year] ,id_Total , date_duc , number_Temp, number_Fix ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS bed
,SUM(amountBes)OVER(  ORDER BY [Year] ,id_Total , date_duc , number_Temp, number_Fix ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS bes
FROM (
SELECT [Counter], id_doc , [Year] ,id_Total , date_duc ,Number_Temp , number_fix , sumbed , sumbes ,  
amountBed = CASE WHEN id_Total  LIKE '1%' OR  Id_Total LIKE '2%' OR  Id_Total LIKE '7%' OR  Id_Total LIKE '8%' THEN (tt.sumbed-tt.sumbes) ELSE 0 END ,
amountBes=CASE WHEN Id_Total LIKE '3%' OR Id_Total LIKE '4%' OR Id_Total LIKE '5%' OR Id_Total LIKE '6%' OR Id_Total LIKE '9%' THEN (tt.sumbes-tt.sumbed)ELSE 0 END ,
ROW_NUMBER() OVER (PARTITION BY [Year] ,id_Total , date_duc , Number_Temp , number_fix  ORDER BY  date_duc )AS  row_no
FROM (
SELECT * FROM cteBed cb WHERE cb.row_no = 1
UNION ALL
SELECT * FROM cteBes cb WHERE cb.row_no = 1
) AS tt ([Counter], id_doc , [Year] ,id_Total , date_duc ,Number_Temp , number_fix , sumbed , sumbes,row_no ) WHERE not(sumbed = 0 AND sumbes = 0)
) AS rr

اگه تو یه دستور Select از Row_Number استفاده کرده باشم ، اول خروجی رو بدست میاره بعد خروجی رو بر حسب نوع مرتب سازی مربوط به Row_Number مرتب میکنه ؟ و دیگه اینکه خروجی دستور اول که شامل Row_Number هست بعد از مرتب شدن به همون صورت به دست دستور دوم (یا همون Select بیرونی) میرسه یا باز باید روی اون نیز مرتب سازی انجام بدم ؟ اصلا جای ستونی که مربوط به Row_Number هست اول یا آخر فرق میکنه ؟
اینارو به این خاطر پرسیدم ، چون هر بار داده هام جواب متفاوتی میداد و نتونستم تشخیص بدم . ممنون
مطالب
پیاده سازی عملیات صفحه بندی (paging) در sql server

در خیلی مواقع ملاحظه میشود که برای نمایش تعدادی از رکوردهای یک جدول در پایگاه داده، کل مقادیر موجود درآن توسط یک دستور select به دست می‌آید و صفحه‌بندی خروجی، به کنترلهای موجود سپرده میشود. اگر پایگاه داده ما دارای تعداد زیادی رکورد باشد، آن موقع است که دچار مشکل می‌شویم. فرض کنید به طور همزمان ۵ نفر (که تعداد زیادی نیستند) از برنامه ما که شامل ۱۰۰۰۰۰ سطر داده میباشد استفاده کنند و در هر صفحه، ۱۰ رکورد نمایش داده شود و صفحه‌بندی ما از نوع معقولی نباشد. در این صورت به جای اینکه با ۵×۱۰ رکورد داده را بارگزاری کنیم، ۵×۱۰۰۰۰۰ رکورد یعنی ۵۰۰۰۰۰ رکورد را برای به دست آوردن ۵۰ رکورد بارگزاری میکنیم. در زیر روشی شرح داده میشود که توسط آن، این سربار اضافه از روی برنامه و سرورهای مربوطه حذف شود. به stored procedure و توضیحات مربوط به آن توجه فرمایید :

CREATE PROCEDURE sp_PagedItems
(
 @Page int,
 @RecsPerPage int
)
AS

-- We don't want to return the # of rows inserted
-- into our temporary table, so turn NOCOUNT ON
SET NOCOUNT ON


--Create a temporary table
CREATE TABLE #TempItems
(
ID int IDENTITY,
Name varchar(50),
Price currency
)


-- Insert the rows from tblItems into the temp. table
INSERT INTO #TempItems (Name, Price)
SELECT Name,Price FROM tblItem ORDER BY Price

-- Find out the first and last record we want
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1)

-- Now, return the set of paged records, plus, an indiciation of we
-- have more records or not!
SELECT *,
MoreRecords =
(
 SELECT COUNT(*)
 FROM #TempItems TI
 WHERE TI.ID >= @LastRec
)
FROM #TempItems
WHERE ID > @FirstRec AND ID < @LastRec


-- Turn NOCOUNT back OFF
SET NOCOUNT OFF
در این کد دو پارامتر از نوع integer تعریف میکنیم. اول پارامتر @Page که مربوط به شماره صفحه‌ای می‌باشد که قصد دارید آن‌را بارگزاری نمایید. دومین پارامتر با نام @RecsPerPage تعداد رکوردهایی است که هر بار میخواهید بارگزاری شوند. مثلا اگر میخواهید هر بار ۱۵ عدد از رکوردها را نمایش دهید، این مقدار را باید برابر ۱۵ قرار دهیم. در مرحله بعد یک جدول موقت با نام #TempItems ساخته شده است که به طور موقت مقادیری را در حافظه نگه میدارد. نکته کلیدی که جلوتر از آن استفاده شده، ستون با نام ID است که از نوع auto-increment بوده و روی جدول موقت تعریف شده است. این ستون شناسه هر سطر را در خود نگه میدارد که به صورت اتوماتیک بالا میرود و جزء لاینفکی از این نوع paging میباشد. پس از آن جدول موقت را توسط رکوردهای جدول واقعی با نام tblItem توسط دستور select پر میکنیم.

در مرحله بعد شماره اولین و آخرین سطر مورد نظر را بر اساس پارامترهای ورودی محاسبه کرده و در متغیرهای @FirstRec و @LastRec می‌ریزیم.
برای استفاده از این کد فقط کافیست که پارامترهای ورودی را مقداردهی نمایید. مثلا اگر میخواهید در یک کنترل Grid از آن استفاده کنید باید ابتدا یک کوئری داشته باشید که تعداد کل سطرها را به شما بدهد و بر اساس این مقدار تعداد صفحات مورد نظر را به دست آورید. پس از آن با کلیک روی هر کدام از شماره صفحات آن را به عنوان مقدار به پارامتر مورد نظر بفرستید و از آن لذت ببرید. 

اشتراک‌ها
صفحه بندی یک کوئری با Sql Server
Table of Contents

    Introduction
        Building the Environment for Testing
        Paging rows with Limit
        Paging in SQL Server 2012
        Comparing the Queries - ROW_NUMBER vs OFFSET/FETCH
    Conclusion
    References
    See Also
    Other Languages
صفحه بندی یک کوئری با Sql Server
نظرات مطالب
نمایش ساختارهای درختی توسط jqGrid
چند مثال در این زمینه:
Functionality -> Add tree node (مثال رسمی)
Insert a row (روی صفحه کلیک راست کرده و سورس آن‌را مطالعه کنید)
Add new rows to jqGrid Treegrid model (در استک اورفلو جستجو کنید، مطالب خوبی در مورد jqGrid دارد. تا امروز 8000 سؤال مرتبط دارد. امکان ندارد در زمینه‌ی jqGrid مشکلی داشته باشید و در آنجا مطرح نشده باشد)
مطالب
آموزش MDX Query - قسمت چهاردهم– Order

در زیر در ابتدا یک کوئری می‌نویسیم و سپس بررسی می‌کنیم که چگونه می‌توان خروجی را مرتب کنیم.

Select
[Measures].[Internet Sales Amount]on columns,
[Product].[Product Categories].[Subcategory] on rows
From [Adventure Works]

کوئری بالا میزان فروش اینترنتی را بر اساس دسته بندی محصولات واکشی می‌کند

در کوئری زیر لیست فروش، براساس میزان فروش اینترنتی مرتب شده است :

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Subcategory].[Subcategory],
[Measures].[Internet Sales Amount]
)on rows
From [Adventure Works]

تابع Order،  ستون یا ردیف خاصی را بر اساس ستون یا ردیف دیگری مرتب می کند .این تابع بر روی کل یک Axis  اعمال میگردد و دو پارامتر دارد .

پارامتر دوم مشخص می کند مرتب سازی پارامتر اول بر اساس چه شاخصی باشد .

همچنین در کوئری زیر نحوه‌ی مرتب کردن به صورت نزولی را خواهیم دید.

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Subcategory].[Subcategory],
[Measures].[Internet Sales Amount],
desc
) on rows
From [Adventure Works]

مرتب سازی به صورت صعودی به شکل زیر می‌باشد

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Subcategory].[Subcategory],
[Measures].[Internet Sales Amount],
asc
) on rows
From [Adventure Works]

از  آنجایی که مرتب سازی به صورت پیش فرض صعودی می باشد، ب کار بردن این کلید واژه ، خیلی لازم نمی باشد .


رویکرد تابع Order  با ساختار سلسله مراتبی 

برای شروع کوئری زیر را اجرا می‌کنیم.

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Internet Sales Amount],
asc
) on rows
From [Adventure Works]

البته در این حالت با نگاه کردن به خروجی متوجه میشوید که عملیات مرتب سازی به درستی انجام نشده است و دلیل این اتفاق رویکرد تابع مرتب سازی به ساختار سلسله مراتبی میباشد . عملا تابع مرتب سازی احترام ویژه ای به ساختار سلسله می گزارد .

حال همان کوئری را به صورت زیر اجرا می‌کنیم :

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Internet Sales Amount],
basc
) on rows
From [Adventure Works]

حرف  در کلمه ی کلیدی  basc  به معنی شکستن ساختار سلسله مراتبی می باشد . در این حالت عملیات مرتب سازی بدون درنظر گرفتن ساختار سلسله مراتبی انجام می گردد .

کوئری‌های زیر تاثیر مرتب سازی نزولی و ساختار سلسله مراتبی را بررسی می‌کنند

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Internet Sales Amount],
desc
) on rows
From [Adventure Works]

در این حالت مرتب سازی نزولی انجام می گردد اما با درنظر گرفتن ساختار سلسله مراتبی

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Internet Sales Amount],
bdesc
) on rows
From [Adventure Works]

در این حالت عمل مرتب سازی نزولی بدون درنظر گرفتن ساختار سلسله مراتبی انجام میگردد .

می توان مرتب سازی را بر اساس یک ستون که در کوئری ذکر نشده است انجام داد . در این حالت نتیجه در ظاهر مرتب نمی باشد .

Select
[Measures].[Internet Sales Amount] on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Reseller Sales Amount],
bdesc
) on rows
From [Adventure Works]

در این کوئری دو ستون وجود دارد اما مرتب سازی براساس یکی از ستون ها انجام می شود

Select
{
[Measures].[Internet Sales Amount],
[Measures].[Reseller Sales Amount]
} on columns,
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Reseller Sales Amount],
bdesc
) on rows
From [Adventure Works]

عملیات مرتب سازی می تواند بر روی هرکدام از Axis  ها جداگانه انجام گردد .

Select
order(
[Product].[Product Categories].[Subcategory],
[Measures].[Reseller Sales Amount],
bdesc
 ) on columns,
{
[Measures].[Internet Sales Amount],
[Measures].[Reseller Sales Amount]
} on rows
From [Adventure Works]

از تابع hierarchize  هم می‌توان برای عملیات مرتب سازی استفاده کرد

Select
[Measures].[Internet Sales Amount] on columns,
hierarchize(
{
[Product].[Subcategory].[Touring Bikes],
[Product].[Subcategory],
[Product].[Subcategory].[Mountain Bikes]
}
)on rows
From [Adventure Works]

برای مرتب سازی ردیف هایی که عملا ارتباطی با هم ندارند از این تابع استفاده می شود . پیش فرض مرتب سازی نزولی می باشد . البته می توانستیم همچنان از تابع Order  استفاده کنیم:

Select
[Measures].[Internet Sales Amount] on columns,
Order(
{
[Product].[Subcategory].[Touring Bikes],
[Product].[Subcategory],
[Product].[Subcategory].[Mountain Bikes]
} , [Measures].[Internet Sales Amount] , basc
)on rows
From [Adventure Works]

حال می‌خواهیم ببینیم چگونه می‌توان با استفاده از تابع hierarchize  مرتب سازی صعودی را انجام دهیم :

Select
[Measures].[Internet Sales Amount] on columns,
hierarchize(
{
[Product].[Subcategory].[Touring Bikes],
[Product].[Subcategory],
[Product].[Subcategory].[Mountain Bikes]
 },
 post
) on rows
From [Adventure Works]

همان طور که مشخص می‌باشد مرتب سازی به درستی صورت نگرفته است؟! دلیل این اتفاق اولویت دادن به ساختار سلسله مراتبی می‌باشد.

برای بررسی بیشتر ابتدا کوئری زیر را فراخوانی نمایید :

Select
[Measures].[Internet Sales Amount] on columns,
non empty order(
crossjoin(
[Product].[Category].[Category],
[Product].[Subcategory].[Subcategory]
 ),
[Measures].[Internet Sales Amount],
desc
) on rows
From [Adventure Works]

همانطور که مشخص می‌باشد، مرتب سازی براساس فروش اینترنتی و با درنظر گرفتن ساختار سلسله مراتبی صورت گرفته است. برای مرتب سازی بدون در نظر گرفتن ساختار سلسله مراتبی کوئری زیر را بنویسید :

Select
[Measures].[Internet Sales Amount] on columns,
non empty order(
crossjoin(
[Product].[Category].[Category],
[Product].[Subcategory].[Subcategory]
),
[Measures].[Internet Sales Amount],
bdesc
) on rows
From [Adventure Works]

در این حالت مرتب سازی بدون در نظر گرفتن ساختار سلسله مراتب انجام می گردد .

در دو کوئری فوق از تابع Non empty  برای حذف ردیف‌های  Null  استفاده شده است.