为什么我们不在表值函数上使用INNER JOIN?

时间:2017-07-27 18:31:13

标签: sql-server user-defined-functions

在网上搜索后,我找不到任何暗示您可以或应该使用具有表值函数的INNER JOIN的内容,我很好奇,为什么?例如,SSRS报告开发人员在报告中使用了一个非常常见的TVF用于多值参数,因此他们可以将结果解析为表格。

CREATE FUNCTION [dbo].[ParmSplit] (
    @List nvarchar(MAX),
    @SplitOn nchar(1) )

RETURNS @RtnValue TABLE (
    SplitValue nvarchar(250) )
AS
BEGIN
    WHILE (CHARINDEX(@SplitOn,@List) > 0)
    BEGIN
        INSERT INTO @RtnValue (SplitValue)
        SELECT SplitValue = LTRIM(RTRIM(SUBSTRING(@List,1,CHARINDEX(@SplitOn,@List) - 1)))
        SET @List = SUBSTRING(@List,CHARINDEX(@SplitOn,@List) + LEN(@SplitOn), LEN(@List))
    END

    INSERT INTO @RtnValue (SplitValue)
    SELECT SplitValue = LTRIM(RTRIM(@List))
    RETURN
END

好吧让我们假设我们有一个状态表,在我们的报告中我们有一个状态多值参数。我们希望将参数中传递的状态与表中的状态进行匹配。这是状态表定义:

CREATE TABLE #StateTable (
    StatID int IDENTITY (1,1)
    ,StateCode char(2) );

插入一些记录:

INSERT INTO #StateTable 
SELECT 'AL';        
INSERT INTO #StateTable 
SELECT 'AK';        
INSERT INTO #StateTable 
SELECT 'AZ';        
INSERT INTO #StateTable 
SELECT 'AR';        
INSERT INTO #StateTable 
SELECT 'CA';        
INSERT INTO #StateTable 
SELECT 'CO';        
INSERT INTO #StateTable 
SELECT 'CT';        
INSERT INTO #StateTable 
SELECT 'DE';        
INSERT INTO #StateTable 
SELECT 'DC';        
INSERT INTO #StateTable 
SELECT 'FL';        
INSERT INTO #StateTable 
SELECT 'GA';        
INSERT INTO #StateTable 
SELECT 'GU';        
INSERT INTO #StateTable 
SELECT 'HI';        
INSERT INTO #StateTable 
SELECT 'ID';        
INSERT INTO #StateTable 
SELECT 'IL';        
INSERT INTO #StateTable 
SELECT 'IN';        
INSERT INTO #StateTable 
SELECT 'IA';        
INSERT INTO #StateTable 
SELECT 'KS';        
INSERT INTO #StateTable 
SELECT 'KY';        
INSERT INTO #StateTable 
SELECT 'LA';        
INSERT INTO #StateTable 
SELECT 'ME';        
INSERT INTO #StateTable 
SELECT 'MD';   

现在使用TVF和INNER JOIN进行查询

DECLARE @MultiValuedParameter varchar(500) = 'IA, KS, KY, LA, ME, MD, IN, IL'

SELECT
    StateCode
FROM #StateTable s
INNER JOIN dbo.ParmSplit(@MultiValuedParameter, ',')  p ON s.StateCode = p.SplitValue​

使用CROSS APPLY的相同查询。

DECLARE @MultiValuedParameter varchar(500) = 'IA, KS, KY, LA, ME, MD, IN, IL'

SELECT
    StateCode
FROM #StateTable
CROSS APPLY dbo.ParmSplit(@MultiValuedParameter, ',')
WHERE SplitValue = StateCode 

CROSS APPLY需要一个有效创建INNER JOIN的WHERE子句。

我总是对此感到好奇。即使此示例仅返回单个列,您仍然可以将其应用于多列表结果。为什么当我们谈论TVF时我们只应该使用CROSS APPLY?

1 个答案:

答案 0 :(得分:0)

实际上,你不会/不应该这样做。您正在应用具有静态值的TVF。当参数从数据集中动态化时,应使用APPLY(CROSS或OUTER)。

任何说你需要/应该使用TVF申请的人?您使用JOIN显示它,我也可以看到该值将其用作子查询。