Khi nào tôi nên sử dụng áp dụng chéo trên tham gia bên trong?


925

Mục đích chính của việc sử dụng CROSS ỨNG DỤNG là gì?

Tôi đã đọc (mơ hồ, thông qua các bài đăng trên Internet) cross applycó thể hiệu quả hơn khi chọn qua các tập dữ liệu lớn nếu bạn đang phân vùng. (Paging xuất hiện trong tâm trí)

Tôi cũng biết rằng CROSS APPLYkhông yêu cầu UDF là bàn bên phải.

Trong hầu hết INNER JOINcác truy vấn (mối quan hệ một-nhiều), tôi có thể viết lại chúng để sử dụng CROSS APPLY, nhưng chúng luôn cung cấp cho tôi các kế hoạch thực hiện tương đương.

Bất cứ ai có thể cho tôi một ví dụ tốt về khi nào CROSS APPLYlàm cho một sự khác biệt trong những trường hợp INNER JOINsẽ làm việc là tốt?


Biên tập:

Đây là một ví dụ tầm thường, trong đó các kế hoạch thực hiện hoàn toàn giống nhau. (Chỉ cho tôi một nơi chúng khác nhau và nơi cross applynhanh hơn / hiệu quả hơn)

create table Company (
    companyId int identity(1,1)
,   companyName varchar(100)
,   zipcode varchar(10) 
,   constraint PK_Company primary key (companyId)
)
GO

create table Person (
    personId int identity(1,1)
,   personName varchar(100)
,   companyId int
,   constraint FK_Person_CompanyId foreign key (companyId) references dbo.Company(companyId)
,   constraint PK_Person primary key (personId)
)
GO

insert Company
select 'ABC Company', '19808' union
select 'XYZ Company', '08534' union
select '123 Company', '10016'


insert Person
select 'Alan', 1 union
select 'Bobby', 1 union
select 'Chris', 1 union
select 'Xavier', 2 union
select 'Yoshi', 2 union
select 'Zambrano', 2 union
select 'Player 1', 3 union
select 'Player 2', 3 union
select 'Player 3', 3 


/* using CROSS APPLY */
select *
from Person p
cross apply (
    select *
    from Company c
    where p.companyid = c.companyId
) Czip

/* the equivalent query using INNER JOIN */
select *
from Person p
inner join Company c on p.companyid = c.companyId

50
Tôi biết đây là NGAY CẢ PICKIER của tôi nhưng 'người biểu diễn' chắc chắn là một từ. Nó chỉ không liên quan đến hiệu quả.
Rire1979

2
Nó rất hữu ích cho sql xquery. kiểm tra này .
ARZ

3
Có vẻ như sử dụng "tham gia vòng lặp bên trong" sẽ rất gần với việc áp dụng chéo. Tôi muốn ví dụ của bạn chi tiết mà tham gia gợi ý là tương đương. Chỉ cần nói tham gia có thể dẫn đến bên trong / vòng lặp / hợp nhất hoặc thậm chí "khác" bởi vì nó có thể sắp xếp lại với các liên kết khác.
crokusek

3
Khi tham gia sẽ tạo ra rất nhiều hàng nhưng bạn chỉ cần đánh giá một hàng tham gia tại một thời điểm. Tôi có một trường hợp là tôi cần một người tự tham gia trên một cái bàn với hơn 100 triệu hàng và đơn giản là không đủ bộ nhớ. Vì vậy, tôi đã đi con trỏ để mang dấu chân bộ nhớ xuống. Từ con trỏ, tôi đã áp dụng chéo như dấu chân bộ nhớ vẫn được quản lý và nhanh hơn 1/3 so với con trỏ.
paparazzo

10
CROSS APPLYcó cách sử dụng rõ ràng trong việc cho phép một tập hợp phụ thuộc vào một tập hợp khác (không giống như JOINtoán tử), nhưng điều đó không đi kèm với chi phí: nó hoạt động giống như một hàm hoạt động trên mỗi thành viên của tập hợp bên trái , do đó, theo thuật ngữ của SQL Server luôn luôn thực hiện một Loop Join, mà hầu như không bao giờ là cách tốt nhất để tham gia các bộ. Vì vậy, sử dụng APPLYkhi bạn cần, nhưng đừng lạm dụng nó JOIN.
Gerardo Lima

Câu trả lời:


667

Ai đó có thể cho tôi một ví dụ hay về việc CROSS ỨNG DỤNG tạo ra sự khác biệt trong những trường hợp INNER THAM GIA sẽ hoạt động tốt không?

Xem bài viết trong blog của tôi để so sánh hiệu suất chi tiết:

CROSS APPLYhoạt động tốt hơn trên những thứ không có JOINđiều kiện đơn giản .

Cái này chọn 3các bản ghi cuối cùng t2cho mỗi bản ghi từ t1:

SELECT  t1.*, t2o.*
FROM    t1
CROSS APPLY
        (
        SELECT  TOP 3 *
        FROM    t2
        WHERE   t2.t1_id = t1.id
        ORDER BY
                t2.rank DESC
        ) t2o

Nó không thể dễ dàng được xây dựng với một INNER JOINđiều kiện.

Bạn có thể có thể làm một cái gì đó như thế bằng cách sử dụng CTEchức năng và cửa sổ:

WITH    t2o AS
        (
        SELECT  t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
        FROM    t2
        )
SELECT  t1.*, t2o.*
FROM    t1
INNER JOIN
        t2o
ON      t2o.t1_id = t1.id
        AND t2o.rn <= 3

, nhưng điều này ít đọc và có thể kém hiệu quả hơn.

Cập nhật:

Mới kiểm tra.

masterlà một bảng khoảng 20,000,000hồ sơ với một PRIMARY KEYtrên id.

Truy vấn này:

WITH    q AS
        (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    master
        ),
        t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
JOIN    q
ON      q.rn <= t.id

chạy trong gần 30giây, trong khi cái này:

WITH    t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
CROSS APPLY
        (
        SELECT  TOP (t.id) m.*
        FROM    master m
        ORDER BY
                id
        ) q

là ngay lập tức.


2
Xem phần cuối của liên kết của Ariel. Một truy vấn row_number () cũng đẹp như vậy và thậm chí không yêu cầu tham gia. Vì vậy, tôi không nghĩ rằng tôi nên sử dụng áp dụng chéo cho tình huống này (chọn top 3, phân vùng theo t1.id).
Jeff Meatball Yang

375
Mặc dù đây là câu trả lời phổ biến nhất nhưng tôi không nghĩ nó trả lời câu hỏi thực tế "Mục đích chính của việc sử dụng CROSS ỨNG DỤNG là gì?". Mục đích chính là để cho phép các hàm bảng với các tham số được thực thi một lần trên mỗi hàng và sau đó nối với kết quả.
MikeKulls

5
@ Mike: làm thế nào để bạn gọi một TVFvới INNER JOIN?
Quassnoi

15
@MikeKulls Có, nhưng OP không yêu cầu mục đích chính là sử dụng CROSS APPLY, anh ấy đã hỏi khi nào nên chọn nó INNER JOIN, khi nào thì nó cũng hoạt động.
ErikE

8
Điều đáng nói là đây được gọi là lateral joinSQL tiêu chuẩn (ANSI)
a_horse_with_no_name

198

cross applyđôi khi cho phép bạn làm những việc mà bạn không thể làm với inner join.

Ví dụ (một lỗi cú pháp):

select F.* from sys.objects O  
inner join dbo.myTableFun(O.name) F   
on F.schema_id= O.schema_id

Đây là một lỗi cú pháp , bởi vì, khi được sử dụng với inner join, các hàm bảng chỉ có thể lấy các biến hoặc hằng làm tham số. (Tức là, tham số chức năng bảng không thể phụ thuộc vào cột của bảng khác.)

Tuy nhiên:

select F.* from sys.objects O  
cross apply ( select * from dbo.myTableFun(O.name) ) F  
where F.schema_id= O.schema_id

Đây là hợp pháp.

Chỉnh sửa: Hoặc cách khác, cú pháp ngắn hơn: (bởi ErikE)

select F.* from sys.objects O  
cross apply dbo.myTableFun(O.name) F
where F.schema_id= O.schema_id

Biên tập:

Lưu ý: Informix 12.10 xC2 + có Bảng dẫn xuất bên và Postgresql (9.3+) có các truy vấn con bên có thể được sử dụng cho hiệu ứng tương tự.


11
Tôi nghĩ rằng đây là lý do đằng sau tại sao chúng ta đã áp dụng chéo. Nếu bạn kiểm tra liên kết dưới đây thì đây là điều đầu tiên MS nói về việc áp dụng chéo. Nó có thể có những công dụng khác nhưng tôi nghĩ đây là lý do nó được giới thiệu. Không có nó, các chức năng bảng sẽ không thể sử dụng được trong nhiều tình huống. technet.microsoft.com/en-us/l
Library / ms175156.aspx

áp dụng chéo cũng tạo ra một kế hoạch thực hiện tốt khi được kết hợp với các hàm bảng nội tuyến trong khi vẫn duy trì tính mô đun rất cần thiết.
Nurettin

14
Không SELECTcần thiết bên trong CROSS APPLY. Hãy thử CROSS APPLY dbo.myTableFun(O.name) F.
ErikE

1
@ErikE chắc chắn, bạn luôn có thể sử dụng cú pháp kém linh hoạt hơn để áp dụng chéo. Tôi đã hiển thị phiên bản tổng quát hơn mà đôi khi bạn có thể sử dụng để tránh đưa các cột khó tính vào truy vấn.
Nurettin

2
Tham gia bên trong @Bolu sẽ không hoạt động nếu tham số chức năng bảng phụ thuộc vào cột của bảng khác (còn gọi là tham chiếu bên ngoài) trong lựa chọn bên ngoài. Nó sẽ hoạt động nếu tham số chức năng bảng là một chữ hoặc một biến. Áp dụng chéo sẽ làm việc trong cả hai trường hợp.
Nurettin

175

Hãy xem xét bạn có hai bảng.

BẢNG MASTER

x------x--------------------x
| Id   |        Name        |
x------x--------------------x
|  1   |          A         |
|  2   |          B         |
|  3   |          C         |
x------x--------------------x

BẢNG CHI TIẾT

x------x--------------------x-------x
| Id   |      PERIOD        |   QTY |
x------x--------------------x-------x
|  1   |   2014-01-13       |   10  |
|  1   |   2014-01-11       |   15  |
|  1   |   2014-01-12       |   20  |
|  2   |   2014-01-06       |   30  |
|  2   |   2014-01-08       |   40  |
x------x--------------------x-------x

Có nhiều tình huống chúng ta cần thay thế INNER JOINbằng CROSS APPLY.

1. Tham gia hai bảng dựa trên TOP nkết quả

Xem xét nếu chúng ta cần chọn IdNametừ Mastervà hai ngày cuối cùng cho mỗi Idtừ Details table.

SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
INNER JOIN
(
    SELECT TOP 2 ID, PERIOD,QTY 
    FROM DETAILS D      
    ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID

Các truy vấn trên tạo ra kết quả sau.

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-12   |  20   |
x------x---------x--------------x-------x

Xem, nó đã tạo kết quả cho hai ngày cuối cùng với hai ngày cuối cùng Idvà sau đó chỉ tham gia các bản ghi này trong truy vấn bên ngoài Id, điều này là sai. Điều này sẽ được trả về cả Ids1 và 2 nhưng nó chỉ trả về 1 vì 1 có hai ngày cuối cùng. Để thực hiện điều này, chúng ta cần sử dụng CROSS APPLY.

SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
CROSS APPLY
(
    SELECT TOP 2 ID, PERIOD,QTY 
    FROM DETAILS D  
    WHERE M.ID=D.ID
    ORDER BY CAST(PERIOD AS DATE)DESC
)D

và hình thành kết quả sau.

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-12   |  20   |
|   2  |   B     | 2014-01-08   |  40   |
|   2  |   B     | 2014-01-06   |  30   |
x------x---------x--------------x-------x

Đây là cách nó hoạt động. Truy vấn bên trong CROSS APPLYcó thể tham chiếu bảng bên ngoài, nơi INNER JOINkhông thể thực hiện điều này (nó ném lỗi biên dịch). Khi tìm thấy hai ngày cuối cùng, việc tham gia được thực hiện bên trongCROSS APPLY tức là WHERE M.ID=D.ID.

2. Khi chúng ta cần INNER JOIN chức năng sử dụng các chức năng.

CROSS APPLYcó thể được sử dụng thay thế INNER JOINkhi chúng ta cần lấy kết quả từ Masterbảng và a function.

SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
CROSS APPLY dbo.FnGetQty(M.ID) C

Và đây là chức năng

CREATE FUNCTION FnGetQty 
(   
    @Id INT 
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT ID,PERIOD,QTY 
    FROM DETAILS
    WHERE ID=@Id
)

tạo ra kết quả sau

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-11   |  15   |
|   1  |   A     | 2014-01-12   |  20   |
|   2  |   B     | 2014-01-06   |  30   |
|   2  |   B     | 2014-01-08   |  40   |
x------x---------x--------------x-------x

ƯU ĐIỂM BỔ SUNG CỦA ỨNG DỤNG CROSS

APPLY có thể được sử dụng để thay thế cho UNPIVOT . Hoặc CROSS APPLYhoặc OUTER APPLYcó thể được sử dụng ở đây, đó là hoán đổi cho nhau.

Xem xét bạn có bảng dưới đây (được đặt tên MYTABLE ).

x------x-------------x--------------x
|  Id  |   FROMDATE  |   TODATE     |
x------x-------------x--------------x
|   1  |  2014-01-11 | 2014-01-13   | 
|   1  |  2014-02-23 | 2014-02-27   | 
|   2  |  2014-05-06 | 2014-05-30   | 
|   3  |     NULL    |    NULL      |
x------x-------------x--------------x

Các truy vấn dưới đây.

SELECT DISTINCT ID,DATES
FROM MYTABLE 
CROSS APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)

mang lại cho bạn kết quả

  x------x-------------x
  | Id   |    DATES    |
  x------x-------------x
  |  1   |  2014-01-11 |
  |  1   |  2014-01-13 |
  |  1   |  2014-02-23 |
  |  1   |  2014-02-27 |
  |  2   |  2014-05-06 |
  |  2   |  2014-05-30 | 
  |  3   |    NULL     | 
  x------x-------------x

4
Ví dụ tuyệt vời với các bản ghi 2 vs 4 và giúp tôi hiểu bối cảnh cần thiết.
trnelson

13
Câu trả lời này chứng tỏ rằng nó thực sự đáng để cuộn xuống trang thay vì chỉ chọn trang được chấp nhận.
Mostafa Armandi

2
Ví dụ tốt nhất cho đến nay để giải thích việc sử dụng ỨNG DỤNG ... Tôi đã đọc nhiều bài đăng và nhận ra rằng lời giải thích này xóa hình ảnh dưới dạng nước. Rất cám ơn người anh em.
AG7

1
Đối với điểm 1 nơi chúng tôi có 2 hàng cho ID 1 thay vì 4 hàng cho ID 1, 2. Chúng tôi sẽ không sử dụng liên kết trái thay thế.
Joseph Cho

43

Dường như với tôi, CROSS ỨNG DỤNG có thể lấp đầy một khoảng trống nhất định khi làm việc với các trường được tính toán trong các truy vấn phức tạp / lồng nhau và làm cho chúng đơn giản và dễ đọc hơn.

Ví dụ đơn giản: bạn có DoB và bạn muốn trình bày nhiều trường liên quan đến tuổi cũng sẽ dựa vào các nguồn dữ liệu khác (chẳng hạn như việc làm), như Age, Agegroup, AgeAtHires, MinimalRetorrowDate, v.v. để sử dụng trong ứng dụng người dùng cuối của bạn (Ví dụ: Pivot Pivotables).

Các tùy chọn bị hạn chế và hiếm khi thanh lịch:

  • Các truy vấn con THAM GIA không thể giới thiệu các giá trị mới trong bộ dữ liệu dựa trên dữ liệu trong truy vấn chính (nó phải tự đứng).

  • UDF gọn gàng, nhưng chậm vì chúng có xu hướng ngăn chặn các hoạt động song song. Và là một thực thể riêng biệt có thể là một điều tốt (ít mã) hoặc xấu (mã ở đâu).

  • Bàn giao nhau. Đôi khi chúng có thể hoạt động, nhưng chẳng mấy chốc bạn sẽ tham gia các truy vấn con với hàng tấn UNION. Bừa bộn

  • Tạo một chế độ xem đơn mục đích khác, giả sử các tính toán của bạn không yêu cầu dữ liệu thu được giữa chừng thông qua truy vấn chính của bạn.

  • Bảng trung gian. Có ... thường hoạt động và thường là một tùy chọn tốt vì chúng có thể được lập chỉ mục và nhanh, nhưng hiệu suất cũng có thể giảm do các câu lệnh CẬP NHẬT không song song và không cho phép xếp tầng công thức (sử dụng lại kết quả) để cập nhật một số trường trong cùng một tuyên bố. Và đôi khi bạn chỉ muốn làm mọi thứ trong một lần.

  • Các truy vấn lồng nhau. Có tại bất kỳ thời điểm nào, bạn có thể đặt dấu ngoặc đơn trên toàn bộ truy vấn của mình và sử dụng nó làm truy vấn con để bạn có thể thao tác dữ liệu nguồn và các trường được tính toán như nhau. Nhưng bạn chỉ có thể làm điều này rất nhiều trước khi nó trở nên xấu xí. Rất xấu.

  • Lặp lại mã. Giá trị lớn nhất của 3 câu lệnh dài (CASE ... ELSE ... END) là gì? Điều đó sẽ được đọc!

    • Nói với khách hàng của bạn để tự tính toán những thứ chết tiệt.

Tôi đã bỏ lỡ một cái gì đó? Có lẽ, vì vậy hãy bình luận. Nhưng này, CROSS ỨNG DỤNG giống như một ơn trời trong những tình huống như vậy: bạn chỉ cần thêm một cách đơn giản CROSS APPLY (select tbl.value + 1 as someFormula) as crossTblvà voilà! Trường mới của bạn hiện đã sẵn sàng để sử dụng thực tế như nó đã luôn ở đó trong dữ liệu nguồn của bạn.

Các giá trị được giới thiệu thông qua CROSS ỨNG DỤNG có thể ...

  • được sử dụng để tạo một hoặc nhiều trường được tính toán mà không cần thêm các vấn đề về hiệu suất, độ phức tạp hoặc khả năng đọc vào hỗn hợp
  • giống như với THAM GIA, một số câu lệnh CROSS ỨNG DỤNG tiếp theo có thể tự tham khảo: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • bạn có thể sử dụng các giá trị được giới thiệu bởi ỨNG DỤNG CROSS trong các điều kiện THAM GIA tiếp theo
  • Là một phần thưởng, có khía cạnh chức năng Bảng giá trị

Dang, không có gì họ không thể làm!


1
Đây là một +1 lớn từ tôi, vì tôi ngạc nhiên vì nó không được nhắc đến thường xuyên hơn. Có lẽ bạn có thể mở rộng ví dụ này để cho thấy cách bạn có thể thực hiện các phép tính "theo thủ tục" trên chuỗi các giá trị dẫn xuất? Ví dụ: CHÉO Apply (chọn crossTbl.value * tbl.multiplier như nhân) multiTbl - CHÉO Apply (chọn multiTbl.Multiplied / tbl.DerivativeRatio như nguồn gốc) derivedTbl - vv ...
mrmillsy

1
Bất kỳ thông tin / ví dụ nào khác về cách sử dụng Cross Áp dụng thay thế cho CASE..ELSE..END?
przemo_li

3
@przemo_li ỨNG DỤNG có thể được sử dụng để lưu trữ kết quả của một tuyên bố trường hợp (trong số những thứ khác) để đề cập đến nó. Một cấu trúc có thể giống như: CHỌN TRƯỜNG HỢP khi truy vấn con.inter liềnResult> 0 THÌ "có" ELSE "không" KẾT THÚC TỪ MỘT SỐ ỨNG DỤNG NGOÀI RA (chọn CASE ... END ... ELSE làm trung gianResult) làm truy vấn con.
nhạc chuông

14

Áp dụng chéo cũng hoạt động tốt với một trường XML. Nếu bạn muốn chọn các giá trị nút kết hợp với các trường khác.

Ví dụ: nếu bạn có một bảng chứa một số xml

<root>
    <subnode1>
       <some_node value="1" />
       <some_node value="2" />
       <some_node value="3" />
       <some_node value="4" />
    </subnode1>
</root>

Sử dụng truy vấn

SELECT
       id as [xt_id]
      ,xmlfield.value('(/root/@attribute)[1]', 'varchar(50)') root_attribute_value
  ,node_attribute_value = [some_node].value('@value', 'int')
  ,lt.lt_name   
FROM dbo.table_with_xml xt
CROSS APPLY xmlfield.nodes('/root/subnode1/some_node') as g ([some_node])
LEFT OUTER JOIN dbo.lookup_table lt
ON [some_node].value('@value', 'int') = lt.lt_id

Sẽ trả lại kết quả

xt_id root_attribute_value node_attribute_value lt_name
----------------------------------------------------------------------
1     test1            1                    Benefits
1     test1            4                    FINRPTCOMPANY

13

Điều này đã được trả lời rất kỹ thuật, nhưng hãy để tôi đưa ra một ví dụ cụ thể về cách nó cực kỳ hữu ích:

Hãy nói rằng bạn có hai bảng, Khách hàng và Đặt hàng. Khách hàng có nhiều Đơn hàng.

Tôi muốn tạo một chế độ xem cung cấp cho tôi thông tin chi tiết về khách hàng và đơn hàng gần đây nhất mà họ đã thực hiện. Chỉ với THAM GIA, điều này sẽ yêu cầu một số tự tham gia và tổng hợp không đẹp. Nhưng với Cross Apply, nó cực dễ:

SELECT *
FROM Customer
CROSS APPLY (
  SELECT TOP 1 *
  FROM Order
  WHERE Order.CustomerId = Customer.CustomerId
  ORDER BY OrderDate DESC
) T

7

Áp dụng chéo có thể được sử dụng để thay thế truy vấn con trong đó bạn cần một cột của truy vấn con

truy vấn con

select * from person p where
p.companyId in(select c.companyId from company c where c.companyname like '%yyy%')

Ở đây tôi sẽ không thể chọn các cột của bảng công ty vì vậy, sử dụng áp dụng chéo

select P.*,T.CompanyName
from Person p
cross apply (
    select *
    from Company C
    where p.companyid = c.companyId and c.CompanyName like '%yyy%'
) T

5

Tôi đoán nó nên dễ đọc;)

CROSS ỨNG DỤNG sẽ hơi độc đáo đối với những người đọc để nói với họ rằng UDF đang được sử dụng sẽ được áp dụng cho mỗi hàng từ bảng bên trái.

Tất nhiên, có những hạn chế khác trong đó ỨNG DỤNG CROSS được sử dụng tốt hơn THAM GIA mà những người bạn khác đã đăng ở trên.


4

Dưới đây là một bài viết giải thích tất cả, với sự khác biệt về hiệu suất và cách sử dụng của chúng trên THAM GIA.

SQL Server CROSS ÁP DỤNG và NGOÀI ỨNG DỤNG trên THAM GIA

Như được đề xuất trong bài viết này, không có sự khác biệt về hiệu suất giữa chúng cho các hoạt động tham gia bình thường (INNER VÀ CROSS).

nhập mô tả hình ảnh ở đây

Sự khác biệt sử dụng đến khi bạn phải thực hiện một truy vấn như thế này:

CREATE FUNCTION dbo.fn_GetAllEmployeeOfADepartment(@DeptID AS INT)  
RETURNS TABLE 
AS 
RETURN 
   ( 
   SELECT * FROM Employee E 
   WHERE E.DepartmentID = @DeptID 
   ) 
GO 
SELECT * FROM Department D 
CROSS APPLY dbo.fn_GetAllEmployeeOfADepartment(D.DepartmentID)

Đó là, khi bạn phải liên quan đến chức năng. Điều này không thể được thực hiện bằng cách sử dụng INNER THAM GIA, điều này sẽ gây ra lỗi "Số nhận dạng đa phần" D.DepidorID "không thể bị ràng buộc." Ở đây giá trị được truyền cho hàm khi mỗi hàng được đọc. Âm thanh tuyệt vời với tôi. :)


3

Chà, tôi không chắc liệu điều này có đủ điều kiện để sử dụng Cross Apply so với Internal Join hay không, nhưng truy vấn này đã được trả lời cho tôi trong Bài đăng trên diễn đàn sử dụng Cross Apply, vì vậy tôi không chắc có phương pháp tương đương nào sử dụng Internal Join không:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

-- Declare the Topical Neighborhood
@TopicalNeighborhood nchar(255)

NHƯ BẮT ĐẦU

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

Create table  #temp
(
    MessageID         int,
    Subjects          nchar(255),
    SubjectsCount    int
)

Insert into #temp Select MessageID, Subjects, SubjectsCount From Message

Select Top 20 MessageID, Subjects, SubjectsCount,
    (t.cnt * 100)/t3.inputvalues as MatchPercentage

From #temp 

cross apply (select count(*) as cnt from dbo.Split(Subjects,',') as t1
             join dbo.Split(@TopicalNeighborhood,',') as t2
             on t1.value = t2.value) as t
cross apply (select count(*) as inputValues from dbo.Split(@TopicalNeighborhood,',')) as t3

Order By MatchPercentage desc

drop table #temp

KẾT THÚC


3

Bản chất của toán tử ỨNG DỤNG là cho phép tương quan giữa bên trái và bên phải của toán tử trong mệnh đề TỪ.

Ngược lại với THAM GIA, sự tương quan giữa các đầu vào không được phép.

Nói về mối tương quan trong toán tử ỨNG DỤNG, ý tôi là ở phía bên tay phải chúng ta có thể đặt:

  • một bảng dẫn xuất - như một truy vấn con tương quan với một bí danh
  • một hàm có giá trị bảng - một khung nhìn khái niệm với các tham số, trong đó tham số có thể tham chiếu đến phía bên trái

Cả hai có thể trả về nhiều cột và hàng.


2

Đây có lẽ là một câu hỏi cũ, nhưng tôi vẫn thích sức mạnh của CROSS ỨNG DỤNG để đơn giản hóa việc sử dụng lại logic và cung cấp cơ chế "xâu chuỗi" cho kết quả.

Tôi đã cung cấp một SQL Fiddle bên dưới, cho thấy một ví dụ đơn giản về cách bạn có thể sử dụng CROSS ỨNG DỤNG để thực hiện các hoạt động logic phức tạp trên tập dữ liệu của mình mà không làm mọi thứ trở nên lộn xộn. Không khó để ngoại suy từ đây tính toán phức tạp hơn.

http://sqlfiddle.com/#!3/23862/2


1

Mặc dù hầu hết các truy vấn sử dụng CROSS ỨNG DỤNG có thể được viết lại bằng INNER THAM GIA, CROSS ỨNG DỤNG có thể mang lại kế hoạch thực hiện tốt hơn và hiệu suất tốt hơn, vì nó có thể giới hạn tập hợp được tham gia trước khi tham gia xảy ra.

Lấy cắp từ đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.