PDA

View Full Version : عملگر Apply



ali ghaemi
پنج شنبه 29 فروردین 1392, 00:52 صبح
SET NOCOUNT ON;

USE tempdb;

IF OBJECT_ID('dbo.Orders') IS NOT NULL DROP TABLE dbo.Orders;
IF OBJECT_ID('dbo.Customers') IS NOT NULL DROP TABLE dbo.Customers;
GO

CREATE TABLE dbo.Customers
(
customerid CHAR(5) NOT NULL PRIMARY KEY,
city VARCHAR(10) NOT NULL
);

CREATE TABLE dbo.Orders
(
orderid INT NOT NULL PRIMARY KEY,
customerid CHAR(5) NULL REFERENCES Customers(customerid)
);
GO

INSERT INTO dbo.Customers(customerid, city) VALUES('FISSA', 'Madrid');
INSERT INTO dbo.Customers(customerid, city) VALUES('FRNDO', 'Madrid');
INSERT INTO dbo.Customers(customerid, city) VALUES('KRLOS', 'Madrid');
INSERT INTO dbo.Customers(customerid, city) VALUES('MRPHS', 'Zion');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(1, 'FRNDO');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(2, 'FRNDO');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(3, 'KRLOS');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(4, 'KRLOS');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(5, 'KRLOS');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(6, 'MRPHS');
INSERT INTO dbo.Orders(orderid, customerid) VALUES(7, NULL);


SELECT C.customerid, C.city, A.orderid FROM dbo.Customers AS C
CROSS APPLY
(SELECT TOP (2) O.orderid, O.customerid FROM dbo.Orders AS O
WHERE O.customerid = C.customerid
ORDER BY orderid DESC) AS A;


و خروجی اون به این شکله


102995

حالا سوال من این است که عملگر Apply براساس چه روندی این خروجی رو به من داده !!! (تحلیل عمکرد Apply)

tooraj_azizi_1035
پنج شنبه 29 فروردین 1392, 19:59 عصر
سلام
اين يك تحليل شخصي است اگر ايرادي دارد دوستان رفع كنند.
البته از روي پلن اجرا بايد تحليل رو انجام داد.
در كوئري داخلي به خاطر وجود گزاره WHERE نتيجه بستگي به كوئري بيروني دارد چون C.customerid هنوز معلوم نيست.
پس ابتدا كوئري بيروني اجرا شده و بعد كوئري داخلي و نتايج بر اساس فيلد OrderID با هم Join مي شوند و به ترتيب نزولي مرتب شده و 2 تاي اول انتخاب مي شوند. تا اينجا به A رسيده ايم.
سپس به ازاي هر ركورد از جدول Customers تمام ركوردهاي A نمايش داده مي شوند يعني ضرب دكارتي.
البته مطمئنم توضيحاتم ناقص است.:لبخندساده:

ali ghaemi
جمعه 30 فروردین 1392, 00:12 صبح
در كوئري داخلي به خاطر وجود گزاره WHERE نتيجه بستگي به كوئري بيروني دارد چون C.customerid هنوز معلوم نيست.
پس ابتدا كوئري بيروني اجرا شده و بعد كوئري داخلي و نتايج بر اساس فيلد OrderID با هم Join مي شوند و به ترتيب نزولي مرتب شده و 2 تاي اول انتخاب مي شوند. تا اينجا به A رسيده ايم.


در کتابی که این مثال رو زده یک توضیح کلی هم برای عملکرد این عملگر داده


The APPLY operator applies the right table expression to every row from the left input. The
right table expression can refer to the left input’s columns. The right input is evaluated once for
each row from the left. This step unifies the sets produced by matching each left row with the
corresponding rows from the right table expression, and this step returns the combined result.
برداشت من از این مطلب است که هر نتیجه در كوئري داخلی بر روی هر سطر از كوئري بيروني اجرا می شه

ضرب دکارتی هم فکر نمی کنم چون خروجی كوئري داخلی دو سطر است که در این صورت باید خروجی نهایی من حاوی 8 سطر باشه از طرفی اگر یکی از خروجی های كوئري داخلی حاوی Null باشه خروجی نهایی 4 تا می شه !