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
تهیه کوئری بر روی ایندکسهای Full Text Search
با استفاده از 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');
باید دقت داشت که این نوع کوئریها، حساس به حروف کوچک و بزرگ نیستند.
همچنین عبارت وارد شده از نوع یونیکد است. به همین جهت برای جلوگیری از تغییر 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');
و یا نحوهی بکارگیری AND NOT در کوئری ذیل مشخص شدهاست:
-- Simple terms with logical AND NOT SELECT id, title, docexcerpt FROM dbo.Documents WHERE CONTAINS(docexcerpt, N'data AND NOT 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*"');
5) جستجوهای Proximity
Proximity در اینجا به معنای یافتن واژههایی هستند که نزدیک (از لحاظ تعداد فاصله بر حسب کلمات) به واژهای دیگر میباشند.
-- Simple proximity SELECT id, title, docexcerpt FROM dbo.Documents WHERE CONTAINS(docexcerpt, N'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)');
همچنین میتوان مشخص کرد که ترتیب جستجو باید دقیقا بر اساس نحوهی تعریف این کلمات در کوئری باشد:
-- Proximity with max distance and order SELECT id, title, docexcerpt FROM dbo.Documents WHERE CONTAINS(docexcerpt, N'NEAR((problem, data),5, TRUE)'); GO
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 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>
فایل tsenu.xml به صورت پیش فرض برای زبان انگلیسی آمریکایی مورد استفاده قرار میگیرد. اگر محتویات آنرا برای مثال با محتویات XML ایی فوق جایگزین کنید (در حین ذخیره باید دقت داشت که encoding فایل نیاز است Unicode باشد)، سپس باید SQL Server را از این تغییر نیز مطلع نمائیم:
-- Load the US English file EXEC sys.sp_fulltext_load_thesaurus_file 1033; GO
البته اگر اینکار را انجام ندهیم، به صورت خودکار، اولین کوئری که از 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
در ادامه اگر کوئری دوم را که از FORMSOF جهت تعیین روش THESAURUS استفاده کرده است، اجرا کنیم، به یک رکورد خواهیم رسید که در آن واژهی necessity به کمک محتویات فایل tsenu.xml که پیشتر تهیه کردیم، بجای need وجود دارد.
9) جستجو بر روی خواص و متادیتای فایلها
-- Document properties SELECT id, title, docexcerpt FROM dbo.Documents WHERE CONTAINS(PROPERTY(doccontent,N'Authors'), N'Test');
کار با FREETEXT
-- FREETEXT SELECT * FROM dbo.Documents WHERE FREETEXT(docexcerpt, N'data presentation need');
در کوئری فوق، کلیه رکوردهایی که با سه کلمهی وارد شده (به صورت مجزا) به نحوی تطابق داشته باشند (تطابق کامل یا بر اساس تطابقهای معنایی یا دستوری) باز گردانده خواهند شد.
میخواستم بدونم به چه شکل میتوانم متوجه شوم کدام قسمت از برنامه من موجب افزایش مصرف رم شده است؟ برای مثال برنامه من بعد گذشت 1 دقیقه از اجرای آن مصرف رم معادل 5MB دارم ولی پس از گذشت 10 دقیقه به 1GB میرسد.
;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 به دست میآید و صفحهبندی خروجی، به کنترلهای موجود سپرده میشود. اگر پایگاه داده ما دارای تعداد زیادی رکورد باشد، آن موقع است که دچار مشکل میشویم. فرض کنید به طور همزمان ۵ نفر (که تعداد زیادی نیستند) از برنامه ما که شامل ۱۰۰۰۰۰ سطر داده میباشد استفاده کنند و در هر صفحه، ۱۰ رکورد نمایش داده شود و صفحهبندی ما از نوع معقولی نباشد. در این صورت به جای اینکه با ۵×۱۰ رکورد داده را بارگزاری کنیم، ۵×۱۰۰۰۰۰ رکورد یعنی ۵۰۰۰۰۰ رکورد را برای به دست آوردن ۵۰ رکورد بارگزاری میکنیم. در زیر روشی شرح داده میشود که توسط آن، این سربار اضافه از روی برنامه و سرورهای مربوطه حذف شود. به 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
در مرحله بعد شماره اولین و آخرین سطر مورد نظر را بر اساس پارامترهای ورودی محاسبه کرده و در متغیرهای @FirstRec و @LastRec میریزیم.
برای
استفاده از این کد فقط کافیست که پارامترهای ورودی را مقداردهی نمایید.
مثلا اگر میخواهید در یک کنترل Grid از آن استفاده کنید باید ابتدا یک
کوئری داشته باشید که تعداد کل سطرها را به شما بدهد و بر اساس این مقدار
تعداد صفحات مورد نظر را به دست آورید. پس از آن با کلیک روی هر کدام از
شماره صفحات آن را به عنوان مقدار به پارامتر مورد نظر بفرستید و از آن لذت
ببرید.
صفحه بندی یک کوئری با Sql Server
نمایش ساختارهای درختی توسط jqGrid
Functionality -> Add tree node (مثال رسمی)
Insert a row (روی صفحه کلیک راست کرده و سورس آنرا مطالعه کنید)
Add new rows to jqGrid Treegrid model (در استک اورفلو جستجو کنید، مطالب خوبی در مورد jqGrid دارد. تا امروز 8000 سؤال مرتبط دارد. امکان ندارد در زمینهی jqGrid مشکلی داشته باشید و در آنجا مطرح نشده باشد)
در زیر در ابتدا یک کوئری مینویسیم و سپس بررسی میکنیم که چگونه میتوان خروجی را مرتب کنیم.
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]
حرف b در کلمه ی کلیدی 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 استفاده شده است.