इनर ज्वाइन पर क्रॉस एप्लाई कब लगाना चाहिए?


925

CROSS APPLY का उपयोग करने का मुख्य उद्देश्य क्या है ?

मैंने पढ़ा है (अस्पष्ट रूप से, इंटरनेट पर पोस्ट के माध्यम से) जो cross applyबड़े डेटा सेटों का चयन करते समय अधिक कुशल हो सकता है यदि आप विभाजन कर रहे हैं। (पेजिंग दिमाग में आता है)

मुझे यह भी पता है कि CROSS APPLYसही तालिका के रूप में एक यूडीएफ की आवश्यकता नहीं है।

अधिकांश INNER JOINप्रश्नों (एक से कई रिश्तों) में, मैं उन्हें उपयोग करने के लिए फिर से लिख सकता हूं CROSS APPLY, लेकिन वे हमेशा मुझे समान निष्पादन योजना देते हैं।

क्या कोई मुझे इस बात का अच्छा उदाहरण दे सकता है कि CROSS APPLYउन मामलों में क्या फर्क पड़ता है जहां INNER JOINकाम करेगा?


संपादित करें:

यहां एक तुच्छ उदाहरण है, जहां निष्पादन योजनाएं बिल्कुल समान हैं। (मुझे दिखाओ कि वे कहां भिन्न हैं और कहां cross applyतेज / अधिक कुशल हैं)

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
मुझे पता है कि यह मेरे लिए ईवीएन पिकर है लेकिन 'परफॉर्मेंट' सबसे निश्चित रूप से एक शब्द है। यह सिर्फ दक्षता से संबंधित नहीं है।
1919 में Rire1979

2
यह sql xquery के लिए बहुत उपयोगी है। जाँच इस
एआरजेड

3
"इनर लूप जॉइन" का उपयोग करने के लिए लगता है कि यह क्रॉस अप्लाई के बहुत करीब होगा। मैं चाहता हूं कि आपका उदाहरण विस्तृत है जो संकेत से जुड़ता है। केवल यह कहना कि आंतरिक / पाश / मर्ज या "अन्य" में परिणाम हो सकता है क्योंकि यह अन्य जोड़ के साथ फिर से व्यवस्थित हो सकता है।
क्रुकसेक

3
जब जुड़ने से बहुत सारी पंक्तियाँ बनेंगी लेकिन आपको केवल एक पंक्ति में एक बार में शामिल होने का मूल्यांकन करना होगा। मेरे पास एक मामला था कि मुझे 100 मिलियन से अधिक पंक्तियों के साथ एक मेज पर एक स्व-शामिल होने की आवश्यकता थी और सरल पर्याप्त मेमोरी नहीं थी। तो मैं स्मृति पदचिह्न नीचे लाने के लिए कर्सर गया। कर्सर से मैं क्रॉस अप्लाइज़ हो गया क्योंकि अभी भी मेमोरी फ़ुटप्रिंट प्रबंधित है और कर्सर से 1/3 अधिक तेज़ था।
पपराज़ो

10
CROSS APPLYएक सेट को दूसरे ( JOINऑपरेटर के विपरीत ) पर निर्भर करने की अनुमति देने में इसका स्पष्ट उपयोग है , लेकिन यह बिना लागत के नहीं आता है: यह एक फ़ंक्शन की तरह व्यवहार करता है जो बाएं सेट के प्रत्येक सदस्य पर काम करता है , इसलिए, SQL सर्वर शर्तों में हमेशा एक प्रदर्शन करें Loop Join, जो लगभग कभी भी सेट में शामिल होने का सबसे अच्छा तरीका नहीं है। इसलिए, APPLYजब आपको जरूरत हो , उपयोग करें, लेकिन इसके खिलाफ अति प्रयोग न करें JOIN
गेरार्डो लीमा

जवाबों:


667

क्या कोई मुझे एक अच्छा उदाहरण दे सकता है जब CROSS APPLY उन मामलों में फर्क करता है जहां INNER JOIN काम करेगा?

विस्तृत प्रदर्शन तुलना के लिए मेरे ब्लॉग का लेख देखें:

CROSS APPLYउन चीजों पर बेहतर काम करता है जिनकी कोई सरल JOINस्थिति नहीं है ।

यह प्रत्येक रिकॉर्ड से 3पिछले रिकॉर्ड का चयन करता t2है 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

यह आसानी से एक INNER JOINशर्त के साथ तैयार नहीं किया जा सकता है ।

आप शायद ऐसा कुछ कर सकते हैं जो CTEविंडो और विंडो फ़ंक्शन का उपयोग कर रहा है:

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

, लेकिन यह कम पठनीय है और शायद कम कुशल है।

अपडेट करें:

बस जाँच की गई।

masterऑन के 20,000,000साथ रिकॉर्ड के बारे में एक तालिका है ।PRIMARY KEYid

यह प्रश्न:

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

लगभग एक 30सेकंड के लिए चलता है , जबकि यह एक:

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

तुरंत है।


2
एरियल के लिंक का अंत देखें। एक row_number () क्वेरी बस के रूप में अच्छा है और इसमें शामिल होने की भी आवश्यकता नहीं है। इसलिए मुझे नहीं लगता कि मुझे इस स्थिति के लिए क्रॉस अप्लाई (टॉप 3 चुनें, विभाजन t1.id द्वारा) का उपयोग करना चाहिए।
जेफ मीटबॉल यांग

375
यद्यपि यह सबसे लोकप्रिय उत्तर है, मुझे नहीं लगता कि यह वास्तविक प्रश्न का उत्तर देता है "CROSS APPLY का उपयोग करने का मुख्य उद्देश्य क्या है?"। मुख्य उद्देश्य प्रति पंक्ति में एक बार निष्पादित होने वाले मापदंडों के साथ तालिका कार्यों को सक्षम करना और फिर परिणामों में शामिल होना है।
माइककूल

5
@Mike: कैसे आप एक कहते हैं TVFके साथ INNER JOIN?
क्वासोनि

15
@ मायकेकुलस हाँ, लेकिन ओपी ने उपयोग करने के मुख्य उद्देश्य के लिए नहीं CROSS APPLYपूछा, उन्होंने पूछा INNER JOINकि इसे कब चुनना है , जब यह काम करेगा।
एरिक

8
यह उल्लेखनीय है कि इसे lateral joinमानक (ANSI) एसक्यूएल में कहा जाता है
a_horse_with_no_name

198

cross applyकभी-कभी आपको उन चीजों को करने में सक्षम बनाता है जो आप नहीं कर सकते inner join

उदाहरण (एक सिंटैक्स त्रुटि):

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

यह एक सिंटैक्स त्रुटि है , क्योंकि, जब उपयोग किया जाता है inner join, तो तालिका फ़ंक्शन केवल चर या स्थिरांक को पैरामीटर के रूप में ले सकते हैं । (यानी, टेबल फ़ंक्शन पैरामीटर किसी अन्य तालिका के कॉलम पर निर्भर नहीं कर सकता है।)

तथापि:

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

यह कानूनी है।

संपादित करें: या वैकल्पिक रूप से, छोटा वाक्यविन्यास: (एरिक द्वारा)

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

संपादित करें:

नोट: Informix 12.10 xC2 + में लेटरल डेरेव्ड टेबल्स और Postgresql (9.3+) में लेटरल सबक्वेरीज़ हैं जिनका उपयोग एक समान प्रभाव के लिए किया जा सकता है।


11
मुझे लगता है कि हमारे पास क्रॉस अप्लाई करने के पीछे यही तर्क है। यदि आप नीचे दिए गए लिंक की जांच करते हैं तो यह पहली बात है जो एमएस क्रॉस क्रॉस के बारे में कहता है। इसके अन्य उपयोग हो सकते हैं लेकिन मुझे लगता है कि यही कारण है कि इसे पेश किया गया था। इसके बिना बहुत से परिस्थितियों में टेबल फ़ंक्शन उपयोग करने योग्य नहीं होगा। Technet.microsoft.com/en-us/library/ms175156.aspx
माइककूल

क्रॉस अप्लाई भी एक अच्छी निष्पादन योजना का निर्माण करता है जब इनलाइन टेबल फ़ंक्शन के साथ युग्मित किया जाता है, जबकि बहुत आवश्यक मॉड्यूलरिटी बनाए रखता है।
nurettin

14
SELECTअंदर की कोई जरूरत नहीं CROSS APPLY। कृपया प्रयास करें CROSS APPLY dbo.myTableFun(O.name) F
एरिक

1
@ सुनिश्चित करें, आप हमेशा कम लचीले सिंटैक्स का उपयोग कर सकते हैं पार लागू करने के लिए। मैं और अधिक सामान्यीकृत संस्करण दिखा रहा था जिसे आप कभी-कभी उपयोग कर सकते हैं ताकि क्वेरी में कॉलम की गणना करने के लिए कठिन लाने से बच सकें।
nurettin

2
यदि बाहरी फ़ंक्शन में तालिका फ़ंक्शन पैरामीटर किसी अन्य तालिका के स्तंभ (उर्फ बाहरी संदर्भ) पर निर्भर करता है, तो @Bolu इनर जॉइन काम नहीं करेगा। यह काम करेगा अगर टेबल फ़ंक्शन पैरामीटर एक शाब्दिक या एक चर है। क्रॉस केस दोनों मामलों में काम करेगा।
नुरेटिन

175

विचार करें कि आपके पास दो टेबल हैं।

मास्टर टेबल

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

विवरण

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

कई स्थितियों जहाँ हम प्रतिस्थापित करने की आवश्यकता कर रहे हैं INNER JOINके साथ CROSS APPLY

1. TOP nपरिणामों के आधार पर दो तालिकाओं में शामिल हों

अगर हम चयन करने की आवश्यकता पर विचार करें Idऔर Nameसे Masterप्रत्येक के लिए और पिछले दो तारीखों Idसे 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

उपरोक्त क्वेरी निम्न परिणाम उत्पन्न करती है।

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

देखें, इसने अंतिम दो तारीखों के साथ अंतिम दो तिथियों के लिए परिणाम उत्पन्न किए Idऔर फिर इन रिकॉर्ड्स को केवल बाहरी क्वेरी में शामिल किया गया Id, जो गलत है। यह Ids1 और 2 दोनों वापस आ जाना चाहिए लेकिन यह केवल 1 ही लौटा क्योंकि 1 में अंतिम दो तिथियां हैं। इसे पूरा करने के लिए, हमें उपयोग करने की आवश्यकता है 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

और निम्न परिणाम बनाता है।

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

यहां देखिए यह कैसे काम करता है। अंदर की क्वेरी CROSS APPLYबाहरी तालिका को संदर्भित कर सकती है, जहां INNER JOINयह नहीं हो सकता है (यह संकलन त्रुटि फेंकता है)। अंतिम दो तिथियों का पता लगाने पर, जॉइनिंग CROSS APPLYयानी अंदर किया जाता है WHERE M.ID=D.ID

2. जब हमें INNER JOINफ़ंक्शन का उपयोग करके कार्यक्षमता की आवश्यकता होती है।

CROSS APPLYएक प्रतिस्थापन के रूप में इस्तेमाल किया जा सकता है INNER JOINजब हमें Masterतालिका और ए से परिणाम प्राप्त करने की आवश्यकता होती है function

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

और यहाँ फ़ंक्शन है

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

जो निम्नलिखित परिणाम उत्पन्न करता है

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

फसल आवेदन की अतिरिक्त सलाह

APPLYके लिए एक प्रतिस्थापन के रूप में इस्तेमाल किया जा सकता है UNPIVOT। या तो CROSS APPLYया OUTER APPLYयहां इस्तेमाल किया जा सकता है, जो परस्पर विनिमय कर रहे।

आप नीचे दी गई तालिका (नाम 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

क्वेरी नीचे है।

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

जो आपको परिणाम लाए

  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
2 बनाम 4 रिकॉर्ड के साथ उत्कृष्ट उदाहरण और मुझे उस संदर्भ को समझने में मदद मिली जिसमें इसकी आवश्यकता होगी।
ट्रिलसन

13
यह उत्तर साबित करता है कि यह स्वीकार किए जाने वाले को चुनने के लिए केवल पृष्ठ को नीचे स्क्रॉल करने के लिए वास्तव में लायक है।
मुस्तफा अरमांडी

2
APPLY के उपयोग की व्याख्या करने के लिए अब तक का सबसे अच्छा उदाहरण ... मैंने कई पोस्ट पढ़े हैं और महसूस किया है कि यह स्पष्टीकरण पानी के रूप में तस्वीर को साफ करता है। बहुत धन्यवाद भाई।
AG7

1
बिंदु 1 के लिए जहां हमारे पास आईडी 1 के लिए 4 पंक्तियों के बजाय आईडी 1 के लिए 2 पंक्तियां हैं, 2. क्या हम इसके बजाय सिर्फ एक बाईं ओर का उपयोग नहीं करेंगे।
जोसेफ चो

43

यह मुझे लगता है कि जटिल / नेस्टेड प्रश्नों में परिकलित फ़ील्ड्स के साथ काम करने पर CROSS APPLY एक निश्चित अंतर भर सकता है, और उन्हें सरल और अधिक पठनीय बना सकता है।

सरल उदाहरण: आपके पास एक डीओबी है और आप कई आयु-संबंधित क्षेत्रों को प्रस्तुत करना चाहते हैं जो आपके अंतिम-उपयोगकर्ता अनुप्रयोग में उपयोग के लिए अन्य डेटा स्रोतों (जैसे कि रोजगार), जैसे कि आयु, आयु-समूह, आयु-निर्धारण, न्यूनतम-प्राप्ति आदि पर निर्भर करेगा। (उदाहरण के लिए Excel PivotTables)।

विकल्प सीमित हैं और शायद ही कभी सुरुचिपूर्ण हैं:

  • जोइन सबक्वेरीज़ पेरेंट क्वेरी में डेटा के आधार पर डेटासेट में नए मान नहीं ला सकती हैं (इसे अपने दम पर खड़ा होना चाहिए)।

  • यूडीएफ साफ-सुथरे होते हैं, लेकिन धीमी गति से होते हैं क्योंकि वे समानांतर संचालन को रोकते हैं। और एक अलग इकाई होना एक अच्छा (कम कोड) या एक बुरा (जहां कोड है) चीज हो सकती है।

  • जंक्शन टेबल। कभी-कभी वे काम कर सकते हैं, लेकिन जल्द ही आप बहुत सारे यूनियनों के साथ उप-क्षेत्रों में शामिल हो रहे हैं। बड़ी गड़बड़।

  • अभी तक एक और एकल-उद्देश्य वाला दृश्य बनाएं, अपनी गणना के अनुसार आपके मुख्य क्वेरी के माध्यम से मध्य-प्राप्त डेटा प्राप्त करने की आवश्यकता नहीं है।

  • मध्यस्थ सारणी। हां ... जो आमतौर पर काम करता है, और अक्सर एक अच्छा विकल्प होता है क्योंकि उन्हें अनुक्रमित और तेज किया जा सकता है, लेकिन प्रदर्शन भी अद्यतन हो सकता है क्योंकि अद्यतन स्टेटमेंट समानांतर नहीं हो सकता है और कैस्केड फ़ार्मुलों (पुन: उपयोग परिणामों) को कई क्षेत्रों में अपडेट करने की अनुमति नहीं देता है। एक ही बयान। और कभी-कभी आप केवल एक पास में काम करना पसंद करेंगे।

  • घोंसले के शिकार सवाल। हां, किसी भी बिंदु पर आप अपनी संपूर्ण क्वेरी पर कोष्ठक डाल सकते हैं और इसे एक उप-वर्ग के रूप में उपयोग कर सकते हैं, जिस पर आप स्रोत डेटा और गणना किए गए फ़ील्ड को समान रूप से जोड़ सकते हैं। लेकिन आप बदसूरत होने से पहले केवल इतना ही कर सकते हैं। बहुत बदसूरत।

  • बार-बार कोड। 3 लंबे (CASE ... ELSE ... END) कथनों का सबसे बड़ा मूल्य क्या है? यह पठनीय है!

    • अपने ग्राहकों को खुद लानत की चीजों की गणना करने के लिए कहें।

क्या मैं कुछ भुल गया? शायद, इसलिए बेझिझक टिप्पणी करें। लेकिन हे, CROSS APPLY ऐसी स्थितियों में एक गॉडसेंड की तरह है: आप बस एक सरल CROSS APPLY (select tbl.value + 1 as someFormula) as crossTblऔर वॉयलिया जोड़ते हैं ! आपका नया क्षेत्र अब व्यावहारिक रूप से उपयोग के लिए तैयार है जैसे कि यह आपके स्रोत डेटा में हमेशा से था।

CROSS APPLY के माध्यम से लाया जा सकता है मान ...

  • मिश्रण में प्रदर्शन, जटिलता या पठनीयता मुद्दों को जोड़ने के बिना एक या एक से अधिक परिकलित फ़ील्ड बनाने के लिए उपयोग किया जा सकता है
  • JOINs के साथ, कई बाद के CROPS APPLY विवरण स्वयं को संदर्भित कर सकते हैं: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • आप बाद की JOIN स्थितियों में एक CROSS APPLY द्वारा शुरू किए गए मूल्यों का उपयोग कर सकते हैं
  • एक बोनस के रूप में, टेबल-वैल्यू फ़ंक्शन पहलू है

डांग, ऐसा कुछ भी नहीं है जो वे नहीं कर सकते हैं!


1
यह मेरे लिए एक बड़ा +1 है, क्योंकि मुझे आश्चर्य है कि इसका अधिक बार उल्लेख नहीं किया गया है। शायद आप इस उदाहरण का विस्तार यह दिखाने के लिए कर सकते हैं कि आप व्युत्पन्न मूल्यों की श्रृंखला पर "प्रक्रियात्मक" गणना कैसे कर सकते हैं? जैसे: CROSS APPLY (select crossTbl.value * tbl.multiplier as Multiplied) मल्टीटबल - CROSS APPLY (चयनित मल्टीटैब .ultiplied / tbl.DerivativeRatio जैसा कि व्युत्पन्न, व्युत्पन्न) - आदि ...
mrmillsy

1
CASE..ELSE..END के प्रतिस्थापन के रूप में Cross Apply का उपयोग करने के बारे में कोई और जानकारी / उदाहरण?
przemo_li

3
@przemo_li APPLY का उपयोग किसी केस स्टेटमेंट (अन्य बातों के अलावा) के परिणाम को संग्रहीत करने के लिए किया जा सकता है। एक संरचना कुछ इस तरह हो सकती है: जब सबक्वेरी के रूप में सब्स्क्राइब करें। तब सेलेक्ट करें।
mtone

14

क्रॉस आवेदन एक XML क्षेत्र के साथ भी अच्छी तरह से काम करता है। यदि आप अन्य क्षेत्रों के साथ संयोजन में नोड मानों का चयन करना चाहते हैं।

उदाहरण के लिए, यदि आपके पास एक टेबल है जिसमें कुछ xml है

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

क्वेरी का उपयोग करना

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

एक परिणाम वापस आएगा

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

13

यह पहले ही तकनीकी रूप से बहुत अच्छी तरह से उत्तर दे चुका है, लेकिन मुझे इसका एक ठोस उदाहरण देना चाहिए कि यह कैसे उपयोगी है:

कहते हैं कि आपके पास दो टेबल हैं, ग्राहक और ऑर्डर। ग्राहकों के कई आदेश हैं।

मैं एक ऐसा दृश्य बनाना चाहता हूं जो मुझे ग्राहकों के बारे में विवरण दे, और उनके द्वारा हाल ही में बनाया गया आदेश। सिर्फ जॉन्स के साथ, इसके लिए कुछ आत्म-जुड़ाव और एकत्रीकरण की आवश्यकता होगी जो सुंदर नहीं है। लेकिन क्रॉस अप्लाई के साथ, इसकी सुपर आसान:

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

7

क्रॉस एप्‍लीकेशन का उपयोग सबक्वेरी की जगह के लिए किया जा सकता है, जहां आपको सबक्वेरी के कॉलम की जरूरत होती है

सबक्वेरी

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

यहां मैं क्रॉस लागू का उपयोग करके कंपनी तालिका के कॉलम का चयन करने में सक्षम नहीं होगा

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

मुझे लगता है कि यह पठनीयता होनी चाहिए;)

CROSS APPLY पढ़ने वाले लोगों के लिए कुछ हद तक अद्वितीय होगी कि उन्हें यह बताने के लिए कि UDF का उपयोग किया जा रहा है, जो बाईं ओर की तालिका से प्रत्येक पंक्ति पर लागू किया जाएगा।

बेशक, ऐसी अन्य सीमाएं हैं जहां जॉन्स की तुलना में एक CROSS APPLY का बेहतर उपयोग किया जाता है जिसे अन्य मित्रों ने ऊपर पोस्ट किया है।


4

यहाँ एक लेख है जो यह सब बताता है, उनके प्रदर्शन अंतर और JOINS पर उपयोग के साथ।

एसक्यूएल सर्वर क्रॉप एप्लायन्स और जॉयर्स पर ओवर एप्लाय

जैसा कि इस लेख में सुझाया गया है, उनके बीच सामान्य जुड़ाव संचालन (INNER AND CROSS) के लिए कोई अंतर नहीं है।

यहां छवि विवरण दर्ज करें

उपयोग अंतर तब आता है जब आपको इस तरह से क्वेरी करनी होती है:

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)

यही है, जब आपको फ़ंक्शन से संबंधित होना है। यह INNER JOIN का उपयोग करके नहीं किया जा सकता है, जो आपको त्रुटि देगा "बहु-भाग पहचानकर्ता" D.DepboxID "बाध्य नहीं किया जा सकता है।" यहां मान फ़ंक्शन को पास किया जाता है क्योंकि प्रत्येक पंक्ति पढ़ी जाती है। मुझे शांत लगता है। :)


3

वैसे मुझे यकीन नहीं है कि यह क्रॉस अप बनाम इनर जॉइन का उपयोग करने के लिए एक कारण के रूप में योग्य है, लेकिन क्रॉस क्वेरी का उपयोग करते हुए एक फोरम पोस्ट में मेरे लिए इस प्रश्न का उत्तर दिया गया था, इसलिए मुझे यकीन नहीं है कि इनर जॉइन का उपयोग करने वाला एक समान तरीका है:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

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

के रूप में BEGIN

-- 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

समाप्त


3

APPLY ऑपरेटर का सार FROM क्लॉज में ऑपरेटर के बाएँ और दाएँ पक्ष के बीच सहसंबंध बनाने की अनुमति देता है।

JOIN के विपरीत, आदानों के बीच संबंध की अनुमति नहीं है।

APPLY ऑपरेटर में सहसंबंध के बारे में बात करते हुए, मेरा मतलब है कि हम दाहिने हाथ की तरफ रख सकते हैं:

  • एक व्युत्पन्न तालिका - एक उपनाम के साथ एक सहसंबद्ध उपकुंजी के रूप में
  • एक टेबल वैल्यू फ़ंक्शन - मापदंडों के साथ एक वैचारिक दृष्टिकोण, जहां पैरामीटर बाईं ओर संदर्भित कर सकता है

दोनों कई कॉलम और पंक्तियाँ लौटा सकते हैं।


2

यह शायद एक पुराना सवाल है, लेकिन मैं अभी भी तर्क के पुन: उपयोग को आसान बनाने और परिणामों के लिए "चाइनिंग" तंत्र प्रदान करने के लिए CROSS APPLY की शक्ति से प्यार करता हूं।

मैंने नीचे एक एसक्यूएल फिडेल प्रदान किया है, जो एक सरल उदाहरण दिखाता है कि कैसे आप सभी गन्दा हो रही चीजों के बिना अपने डेटा सेट पर जटिल तार्किक संचालन करने के लिए CROSS APPLY का उपयोग कर सकते हैं। यह अधिक जटिल गणनाओं से बाहर निकालने के लिए मुश्किल नहीं है।

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


1

जबकि अधिकांश प्रश्न जो CROSS APPLY को नियोजित करते हैं, उन्हें INNER JOIN का उपयोग करके फिर से लिखा जा सकता है, CROSS APPLY बेहतर निष्पादन योजना और बेहतर प्रदर्शन प्राप्त कर सकता है, क्योंकि यह शामिल होने से पहले सेट किए जा रहे सेट को सीमित कर सकता है।

यहां से चोरी हुई

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.