0

我需要:所有过境点,以及当年的 AppData 记录(如果有,则为空)。应始终返回 38,244 条记录。

发生了什么:如果我在 2012 年运行它,我会得到所有行;如果我在 2013 年运行它,我只会得到 19248 行。

在第一个应用程序中,一条记录被插入到 AppData 表中。可能会有当年没有记录的过境点。在第 2 次或第 3 次申请时,它是一条更新记录;总会有与过境点相关的记录。

我已经在这几天了。非常感谢任何帮助!

表数据交叉表 - CRID, int

AppData 表 AppID、AppDate、AppYear。

    ALTER FUNCTION [dbo].[fnGetAppData2]
    (
-- Add the parameters for the function here
    @app as varchar(4),
     @year as varchar(4)
     )
    RETURNS 
    @SCLApps TABLE 

-- Add the column definitions for the TABLE variable here
(AppCRID int,
AppDate date,
AppNbr int, 
AppTruck varchar(10), 
Spray bit,
Cut bit,
Inspect bit,
Invoice date,
AppYear int)

    AS
    BEGIN
    --for 1st app
-- Fill the table variable with the rows for your result set

If @app = 1

INSERT @SCLApps (AppCRID,AppDate,AppTruck,Cut,Inspect,Spray,Invoice,AppNbr)
SELECT Crossings.CRID,

--application date
(CASE WHEN @app = 1 THEN
App1Date 
WHEN @app = 2 THEN
App2Date
WHEN @app = 3 THEN
App3Date
ELSE
Null
END), 

--application truck
(CASE WHEN @app = 1 THEN
App1Truck
WHEN @app = 2 THEN
App2Truck
WHEN @app = 3 THEN
App3Truck
ELSE
Null
END), 

--app cut
(CASE WHEN @app = 1 THEN
App1Cut
WHEN @app = 2 THEN
App2Cut
WHEN @app = 3 THEN
App3Cut
ELSE
Null
END), 

--app inspect
(CASE WHEN @app = 1 THEN
App1Inspect
WHEN @app = 2 THEN
App2Inspect
WHEN @app = 3 THEN
App3Inspect
ELSE
Null
END), 

--app spray  
(CASE WHEN @app = 1 THEN
    App1Spray
WHEN @app = 2 THEN
    App2Spray
WHEN @app = 3 THEN
    App3Spray
    ELSE
Null
END),

--invoice
(CASE WHEN @app = 1 THEN
    App1InvDate
WHEN @app = 2 THEN
    App2InvDate
WHEN @app = 3 THEN
    App3InvDate
    ELSE
Null
END),

--AppNbr
(CASE WHEN @app = 1 THEN
1
WHEN @app = 2 THEN
2
WHEN @app = 3 THEN
3
ELSE
Null
END)

FROM AppData full OUTER JOIN Crossings ON AppData.CRID = Crossings.CRID
WHERE (AppYear = @year or AppYear is null)

ELSE




--for 2nd and 3rd app--------------------------------------

INSERT @SCLApps (AppCRID,AppDate,AppTruck,Cut,Inspect,Spray,Invoice, AppNbr)
SELECT Crossings.CRID,

--application date
(CASE WHEN @app = 1 THEN
App1Date
WHEN @app = 2 THEN
App2Date
WHEN @app = 3 THEN
App3Date
ELSE
''
END), 

--application truck
(CASE WHEN @app = 1 THEN
App1Truck
WHEN @app = 2 THEN
App2Truck
WHEN @app = 3 THEN
App3Truck
ELSE
''
END), 

--app cut
(CASE WHEN @app = 1 THEN
App1Cut
WHEN @app = 2 THEN
App2Cut
WHEN @app = 3 THEN
App3Cut
ELSE
''
END), 

--app inspect
(CASE WHEN @app = 1 THEN
App1Inspect
WHEN @app = 2 THEN
App2Inspect
WHEN @app = 3 THEN
App3Inspect
ELSE
''
END), 

--app spray  
(CASE WHEN @app = 1 THEN
    App1Spray
WHEN @app = 2 THEN
    App2Spray
WHEN @app = 3 THEN
    App3Spray
    ELSE
''
END),

--invoice
(CASE WHEN @app = 1 THEN
    App1InvDate
WHEN @app = 2 THEN
    App2InvDate
WHEN @app = 3 THEN
    App3InvDate
    ELSE
''
END),

--AppNbr
(CASE WHEN @app = 1 THEN
1
WHEN @app = 2 THEN
2
WHEN @app = 3 THEN
3
ELSE
''
END)

FROM AppData full OUTER JOIN Crossings ON AppData.CRID = Crossings.CRID
    WHERE AppYear = @year

RETURN 
    END
4

2 回答 2

1

即使您正在执行 FULL OUTER JOIN,这部分也会消除没有匹配 AppData 的 Crossings:

WHERE AppYear = @year

将最后一部分更改为:

FROM Crossings LEFT JOIN  
(SELECT *
FROM AppData
WHERE WHERE AppYear = @year) AS AppData
ON Crossings.CRID = AppData.CRID

附带说明一下,case 语句有两种格式。您可以通过使用这个来简化:

CASE @app 
WHEN 1 THEN App1Truck
WHEN 2 THEN App2Truck
WHEN 3 THEN App3Truck
ELSE Null END
于 2013-04-12T15:02:30.547 回答
0

首先,您应该使用内联表值函数,而不是多语句表值 UDF。其次,您的 UDF 有两个主要分支,一个用于 @app = 1 时,另一个用于 @app 的任何其他值。然而,在每个分支中,case 语句区分 @app = 1、2、3 的值。这显然是不正确的。
其次,正如@jBrooks 所指出的,AppYear 上的过滤器,如果放在 Where 子句中,将消除在任何表 appyear 中没有匹配的所有行。为了防止这种情况,这个谓词必须是 Join On 子句的一部分。

尝试这个:

CREATE FUNCTION  dbo.fnGetAppData2
( @app as varchar(4),  @year as varchar(4))
Returns Table
As
Return
(
  Select c.CRID,
     Case When @app = 1 Then App1Date When @app = 2 Then App2Date
          When @app = 3 Then App3Date  Else '' End, 

     Case When @app = 1 Then App1Truck When @app = 2 Then App2Truck
          When @app = 3 Then App3Truck Else '' End, 

     Case When @app = 1 Then App1Cut When @app = 2 Then App2Cut
          When @app = 3 Then App3Cut  Else '' End, 

     Case When @app = 1 Then App1Inspect When @app = 2 Then App2Inspect
          When @app = 3 Then App3Inspect Else '' End, 

     Case When @app = 1 Then App1Spray When @app = 2 Then App2Spray
          When @app = 3 Then App3Spray Else '' End, 

     Case When @app = 1 Then App1InvDate When @app = 2 Then App2InvDate
          When @app = 3 Then App3InvDate Else '' End, 

     Case When @app In (1,2,3) Then @app Else '' End 

  From AppData a Full Join Crossings c
      On c.CRID = a.CRID
          And AppYear = Coalesce(@year, AppYear)
)
GO
于 2013-04-12T15:01:32.037 回答