วิธีการเข้าร่วมตารางที่มีฟังก์ชั่นมูลค่าตาราง?


53

ฉันมีฟังก์ชั่นที่ผู้ใช้กำหนด:

create function ut_FooFunc(@fooID bigint, @anotherParam tinyint)
returns @tbl Table (Field1 int, Field2 varchar(100))
as
begin
  -- blah blah
end

ตอนนี้ฉันต้องการเข้าร่วมในตารางอื่นเช่น:

select f.ID, f.Desc, u.Field1, u.Field2
from Foo f 
join ut_FooFunc(f.ID, 1) u -- doesn't work
where f.SomeCriterion = 1

ในคำอื่น ๆ สำหรับทุกFooระเบียนที่SomeCriterion1 ผมต้องการที่จะเห็นFoo IDและDescควบคู่ไปกับค่าของField1และField2ที่กลับมาจากการสำหรับการป้อนข้อมูลของut_FooFuncFoo.ID

ไวยากรณ์ที่จะทำคืออะไร?

คำตอบ:


84

คุณCROSS APPLYไม่จำเป็นต้องเข้าร่วม

คำจำกัดความของนิพจน์ตารางที่เกี่ยวข้องในการรวมจะต้องมีเสถียรภาพ นั่นคือพวกเขาไม่สามารถมีความสัมพันธ์กันเช่นการแสดงออกของตารางหมายถึงสิ่งที่แตกต่างกันขึ้นอยู่กับค่าของแถวในตารางอื่น

select f.ID, f.Desc, u.Field1, u.Field2
from Foo f 
Cross apply ut_FooFunc(f.ID, 1) u
where f.SomeCriterion = ...

0

ฉันรู้ว่ากระทู้เก่าฉันถูกถามคำถามเดียวกันฉันทำแบบทดสอบผลดังต่อไปนี้ ...

บันทึกใน FacCurrencyRate = 14264 ขณะที่ TestFunction ส่งคืน 105 ถ้าดำเนินการอย่างอิสระ

    SELECT F.*, x.CurrencyKey, x.CurrencyName
    FROM ( 
           SELECT CurrencyKey, CurrencyName FROM dbo.TestFunction()
        ) x
    INNER JOIN [dbo].[FactCurrencyRate] F ON x.CurrencyKey = f.CurrencyKey;

เวลาดำเนินการคือ ...

    (14264 rows affected)
    Table 'FactCurrencyRate'. Scan count 1, logical reads 75, physical reads 1, read-ahead reads 73, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'DimCurrency'. Scan count 1, logical reads 2, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 31 ms,  elapsed time = 749 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

หากฉันใช้คำตอบที่แนะนำดังต่อไปนี้ ...

select F.*, x.CurrencyKey, x.CurrencyName from [dbo].[FactCurrencyRate] F
cross apply dbo.TestFunction() x

เวลาดำเนินการและจำนวนผลลัพธ์คือ ...

(1497720 rows affected)
Table 'FactCurrencyRate'. Scan count 1, logical reads 75, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 1, logical reads 38110, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'DimCurrency'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2106 ms,  elapsed time = 43242 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

สิ่งที่ฉันเห็นที่นี่คือการสืบค้นภายในนำเสนอชุดผลลัพธ์ที่ถูกต้องมากขึ้นและเวลาดำเนินการมีประสิทธิภาพมากขึ้น แก้ไขฉันด้วยวิธีที่ดีกว่าเพื่อทำสิ่งเดียวกันให้สำเร็จ!


1
การใช้การไขว้ถูกนำไปใช้กับแต่ละแถวด้านนอก (ดังนั้นทีละแถว) นี่คือสาเหตุที่มันช้ากว่ามากโดยเฉพาะในชุดข้อมูลขนาดใหญ่ ด้วยการย้อนกลับ (เพราะคุณต้องการเพียงผลลัพธ์ที่มีการจับคู่ใน TVF ดังนั้นคุณจึงลดเวลาการ exectuion ลงอย่างมาก (ไม่มีการโทรใดที่ไม่ทำอะไรเลย) รวมถึงจำนวนแถวที่คุณได้รับคืน ส่งคืนแถวมากกว่าแถวแรกเท่าที่ความถูกต้องไปขึ้นอยู่กับความต้องการทางธุรกิจของคุณ
Jonathan Fite

ใช่ฉันเห็นด้วย. อย่างไรก็ตามฉันเขียนโค้ดตามคำถามเริ่มต้นที่ฉันคิดว่ามีความสัมพันธ์แบบหนึ่งถึงหลายอย่างระหว่างตาราง และประการที่สองฉันถูกถามคำถามในการสัมภาษณ์ ขอบคุณ
user3104116
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.