عبارتهای مشترک میان جداول
عبارتهای مشترک میان جداول(CTE) یکی از خصوصیات
جدید SQL Sevrer 2005 میباشد. یک CTE در واقع نام یک مجموعه موقت از
نتایجی است که میتوان از آن در عبارت FROM دستور Select استفاده کرد. بعد
از ایجاد یک CTE میتوان از مجموعه نتایج آن در کلیه دستورات Insert،
Update، Select و Delete دیگری که در محدوده مشابه با این CTE ایجاد
شدهاند استفاده کرد.
مهمترین مزیتی که CTEها برای برنامه نویس فراهم
میکنند در واقع آسانتر کردن پرس و جو از جداول مشتق شده میباشد. با
استفاده از ساختارهای T_SQL قدیمی برای کار با جدوال مشتق شده میبایست برای
اطلاعات بازگشتی از آنها تعریف مجزایی (مانند جداول موقت) صورت گیرد.
استفاده از CTE برای تعریف یک جدول موقت، مشاهده ساختار جداول مشتق شده را
با استفاده از کدهایی که نوشته میشود آسانتر میکند.
یک CTE از سه قسمت اصلی تشکیل شده است:
ü
نام CTE که بعد از کلمه کلیدی WITH قرار
میگیرد.
ü
لیست ستونها.
ü
عبارت پرس و جو که در میان پرانتزهای موجود
بعد از کلمه کلیدی AS قرار میگیرد.
البته در میان این سه بخش استفاده از لیست ستونها اختیاری
میباشد.
ایجاد یک CTE
برای ایجاد یک
CTE باید از گرامری شبیه به گرامر
زیر استفاده کنید. بعد از وارد کردن کدهای زیر در SQL
Server و اجرای آن باید خروجی مشابه با تصویر زير مشاهده کنید.
WITH TopSales (SalesPersonID,
TerritoryID, NumberOfSales)
AS
(
SELECT SalesPersonID,TerritoryID,
Count(*)
FROM Sales.SalesOrderHeader
GROUP BY
SalesPersonID, TerritoryID
)
SELECT * FROM
TopSales
WHERE SalesPersonID
IS NOT
NULL
ORDER
BY NumberOfSales
DESC

چگونه کار میکند
با توجه به اطلاعاتی که قرار است توسط دستور
Select
بازیابی گردند، باید ستونهای تعریف شده در CTE با ستونهای تعیین شده
در این دستور مطابقت داشته باشد. همانطور که مشاهده میکنید این نکته نیز
رعایت شده است:
WITH TopSales
(SalesPersonID,
TerritoryID, NumberOfSales)
همانطور که مشاهده مینمایید ستونهای
تعیین شده در دستور
Select با ستونهای CTE
مرتبط میباشند.
SELECT
SalesPersonID,TerritoryID,
Count(*)
عبارت GROUP BY (برای تشریح عملگر PIVOT حتماً
مثال این قسمت را مطالعه کنید)
از عبارت GROUP
BY برای
دسته بندی اطلاعات بازیابی شده در قالب گروههایی استفاده میشود. با
استفاده از GROUP BY، میتوانید در لیست ستونهای دستور Select به ازاء هر گروه از توابع تراکمی برای ایجاد آمارهای
مخصوص هر گروه استفاده کنید. استفاده از این عبارت هنگامی مفید خواهد بود
که قصد داشته باشید گزارشهایی از جدول دادهها بر اساس اطلاعات ستون(هایی)
ایجاد کنید.
|
نکته: استفاده از توابع تراکمی مانند
count، sum و ...
بدون استفاده از عبارت Group BY خطا در بر دارد
|
استفاده از عبارت GROUP BY
جدول Sales.CreditCard حاوی اطلاعات مربوط به
کارتهای اعتباری میباشد. فرض کنید میخواهیم که کارتهایی که از یک نوع
میباشند و در یک سال مشخص باطل میشوند را مشخص کنید.
برای این کار ابتدا یک پنجره جدید برای ایجاد
پرس و جو ها مانند قبل باز کنید و سپس دستورات زیر را در آن وارد کنید. با
اجرای این دستورات خروجی مشابه با تصویر زير مشاهده خواهید کرد.
Use AdventureWorks
Go
Select CardType,
ExpYear,count(CardType)
AS 'Total Cards'
from Sales.CreditCard
Where ExpYear
in (2006,2007)
group
by ExpYear,CardType
order
by CardType,ExpYear
.jpg)
چگونه کار میکند
در پرس و جوی بالا سه ستون مشخص شده است. دو
ستون اول مستقیماً از جدول Sales.CreditCard بازیابی شده اما ستون سوم
تعداد کل کارتهای در ستون CardType از جدول CreditCard میباشد.
Select CardType,
ExpYear,count(CardType)
AS 'Total Cards'
from Sales.CreditCard
پس از انتخاب ستونها، در قسمت
Where شرط مورد نظر آورده شده است و سپس برای دسته بندی و مرتب کردن نمایش
اطلاعات از عبارتهای Group By و Oreder By استفاده شده است. شرط استفاده
شده در قسمت Where برای بازیابی اطلاعات کارتهایی که در یکی از سالهای 2006
یا 2007 باطل میشوند میباشد.
Where
ExpYear in (2006,2007)
سپس با استفاده از عبارت Group
By اعلام میکنیم که اطلاعات بازیابی شده باید بر اساس نوع کارتها و سال
انقضای آنها باید گروه بندی شوند.
group
by ExpYear,CardType
در انتها با استفاده از عبارت
Order By نحوه نمایش اطلاعات بر اساس
ستونهای ExpYear و CardType به صورت صعودی تنظیم میشود.
order
by CardType,ExpYear
عملگر PIVOT
استفاده از عملگر Pivot زمانی مفید است که قصد
داشته باشید از یک جدول اطلاعات را به صورت ضربدری بازیابی کنید. با
استفاده از این عملگر میتوان اطلاعات درون ردیف ها را به صورت ستون در نظر
گرفت. برای درک بهتر عملکرد این عملگر، مثال قبل را در نظر بگیرید.
در مثال قبل، با توجه به اینکه شرط داده شده
برای کارتهای منقضی در سالهای 2006 و 2007 بود اما اطلاعات کارتهای مشابه
برای این دو سال به صورت مجزا بازیابی شده و در نتیجه تعداد سطور بازیابی
شده زیاد خواهد شد. Pivot با روشی آسانتر خروجی مشابه با خروجی قبل اما در
قالبی خلاصه تر و قابل فهم تر ایجاد میکند.
استفاده از عملگر Pivot
همانطور که قبلاً نیز ذکر شد، جدول
Sales.CreditCards حاوی اطلاعات مربوط به کارتهای اعتباری مشتریان میباشد.
برای درک بهتر عملکرد و بررسی خروجیای که این عملگر ایجاد میکند، عملیاتی
که در قسمت قبل و با استفاده از عبارت Group By انجام گرفت را دوباره انجام
میدهیم.
ابتدا پرس و جوی زیر را در
SQL Server اجرا کنید و خروجی آن را مشاهده کنید تا در قسمت بعد نحوه کار آن را مورد
بررسی قرار دهیم.
Use
AdventureWorks
Go
select
CardType ,[2006]
as Year2006,[2007]
as Year2007
from
(
select
CardType,ExpYear
from
Sales.CreditCard
)piv
Pivot
(
count(ExpYear)
for ExpYear in
([2006],[2007])
)as carddetail
order
by CardType
.jpg)
چگونه کار میکند
ابتدا در اولین دستور
Select ستونهایی که قرار است در خروجی نشان داده شوند به همراه نام مستعار آنها تعیین
شده است.
select
CardType ,[2006]
as Year2006,[2007]
as Year2007
from
|
نکته: اعدادی که در [] قرار گرفته اند در واقع اطلاعات
موجود در رکوردهای جدول مورد استفاده میباشند. اگر مقداری را
در این قسمت وارد کنید که در هیچ یک از رکوردها وجود نداشته
باشد با پیام خطا مواجه خواهید شد.
|
پس از تعیین ستونهای خروجی، نوبت
به بازیابی اطلاعات کلی از جدول Sales.CreditCards میرسد. البته باید یک
عملگر Pivot نیز به خروجی انتساب داده شود.
(
select
CardType,ExpYear
from
Sales.CreditCard
)piv Pivot
حال باید تعداد کارتهایی که در
سال مورد نظر قرار دارند را محاسبه کرد. برای این منظور نیز از کدهای زیر
استفاده شده است.
(
count(ExpYear)
for ExpYear in
([2006],[2007])
)as carddetail
در انتها اطلاعات بدست آمده
براساس نامِ نوع کارتها به صورت صعودی مرتب شده است.
order
by CardType
تابع ()ROW_NUMBER
SQL Server 2005 برای درجه بندی اطلاعات، تابعی
به نام ()Row_Number ارائه کرده است. این تابع یک عدد یکتا و ترتیبی برای
هر رکورد در مجموعه برگشتی ایجاد کرده و برمیگرداند.
استفاده از تابع
Row_Number()
در دستورات زیر برای انتساب یک
عدد یکتا به رکوردهای جدول Sales.SalesPerson از این تابع استفاده شده است
select
SalesPersonID, Bonus,
ROW_NUMBER()
over (order
by SalesPersonID)
as RowsCount
from
Sales.SalesPerson
.jpg)
چگونه کار میکند
در دستور Selectی که در بالا از آن استفاده شده
است، سه ستون برای نشان دادن در خروجی تعیین شده است. ستون سوم قدری با
بقیه تفاوت دارد.
ROW_NUMBER()
over (order
by SalesPersonID
) as
RowsCount
در اینجا با اعمال تابع ()Row_Number
بر روی ستون SalesPersonID و تعیین ترتیب صعودی برای این ستون، در هر رکورد
یک ستون جدید با نام RowsCount اضافه میشود که به ترتیب صعودی مقداری دهی
شده اند.
|
نکته: استفاده از عبارت Oreder
By
برای تعیین
ستونی که Row_Number باید بر آن اعمال شود الزامی است.
|
منابع:
1-
کتاب الکترونیکی
Apress.Beginning.C.Sharp.2008.Databases.From.Novice.to.Professional.Jan.2008
2-
استفاده از کتاب برنامه نویسی بانک
اطلاعاتی در C# و
VB.NET از گروه واژه