为啥 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值

Posted

技术标签:

【中文标题】为啥 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值【英文标题】:Why is SQL server inserting 0 values into my table instead of the correct values using function为什么 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值 【发布时间】:2017-06-29 21:55:35 【问题描述】:

希望有人可以帮助我解决这个问题,因为我完全不知道为什么会这样。

我目前正在对英超联赛的比赛结果进行一些分析,作为其中的一部分,我创建了一个多语句表 UDF。

此函数接受 HomeTeam、AwayTeam 和 MatchDate 参数,然后计算在指定的比赛日期之前主队和客队之间历史上赢、平或输的每场比赛结果。

这个函数手动调用就可以正常工作,返回值如

 Home   Away    Draw
   0      8       4

我想将此信息添加到我的匹配表中的每个匹配结果中,因此创建了一个查询以从临时表中移动匹配项,使用 OUTER APPLY 和插入这些值的函数。(我还 OUTER APPLY 之前的另一个函数到这个工作正常。)然后插入到我的 MatchData 表中。

如果我只选择值,则查询有效,但如果我插入到我的 MatchData 表中,则这些值都填充为 0。

我已经尝试了很多测试,这些测试确认如果我使用 SELECT into 也会发生这种情况,除非表是临时的。

要补充的是,在任何时候都没有转换有问题的值,它们一直保持为整数,并且目标列也是 int 类型。

希望有人能给我一些关于下一步尝试的想法。代码如下。对任何写得不好的地方表示歉意,因为到目前为止我已经混淆了很多代码,试图让它插入正确的值

提前致谢!

这是存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [Load].[MoveToMatchData]
AS 
BEGIN
    INSERT INTO Football.MatchData.PremierLeague
        SELECT * 
        FROM
            (SELECT 
                 [League], [MatchID], [Season], 
                 [MatchDate], [HomeTeam], [AwayTeam],
                 [FTHomeGoals], [FTAwayGoals], [FTResult],
                 [HTHomeGoals], [HTAwayGoals], [HTResult],
                 [Referee], [HomeShots], [AwayShots],
                 [HomeShotsOnTarget], [AwayShotsOnTarget],
                 [HomeFouls], [AwayFouls], [HomeCorners], [AwayCorners],
                 [HomeYellows], [AwayYellows], [HomeReds], [AwayReds]
             FROM 
                 [Football].[Load].[Staging_MatchData] AS a
             WHERE 
                 League = 'E0') AS a

  OUTER APPLY

  (
  SELECT * FROM Football.Load.CreateRelativeTable_Prem
  (a.MatchDate, a.HomeTeam, a.AwayTeam, a.Season, A.League)
  ) as b

  OUTER APPLY 

这是 UDF

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [Load].[GetH2HRecords]
     (@HomeTeam varchar(50), @AwayTeam varchar(50), @MatchDate date)
RETURNS @H2H TABLE
(
Home int,
Away int,
Draw int
)
AS 

BEGIN

DECLARE @FromDate date
SET @FromDate = DATEADD(yyyy,-10,@MatchDate)
INSERT INTO @H2H

SELECT
a.[Number of Matches] as HomeHTH, b.[Number of Matches] as AwayHTH, c.[Number of Matches] as DrawHTH
FROM
    (
    SELECT 
    COUNT(MatchID) as [Number of Matchesh]
    FROM MatchData.PremierLeague
    WHERE HomeTeam = @HomeTeam 
    AND AwayTeam = @AwayTeam
    AND MatchDate > @FromDate
    AND FTResult = 'H'
    ) as a

    OUTER APPLY

    (
    SELECT 
    COUNT(MatchID) as [Number of Matchesa]
    FROM MatchData.PremierLeague
    WHERE HomeTeam = @HomeTeam
    AND AwayTeam = @AwayTeam
    AND MatchDate > @FromDate
    AND FTResult = 'A'
    ) as b

    OUTER APPLY

    (
    SELECT 
    COUNT(MatchID) as [Number of Matchesd]
    FROM MatchData.PremierLeague
    WHERE HomeTeam = @HomeTeam
    AND AwayTeam = @AwayTeam
    AND MatchDate > @FromDate
    AND FTResult = 'D'
    ) as c

RETURN

END


  (
  SELECT * FROM Football.Load.GetH2HRecords
  (a.HomeTeam, a.AwayTeam, a.MatchDate)
  ) as c

  END

【问题讨论】:

表名中有数据库有什么原因吗?您是否插入到不同的(链接的?)服务器? 查询中不涉及链接服务器,我发现完全限定我的表名对我来说效果更好,因为它可以阻止事情进入默认数据库,因为我经常处理不同的项目,这些项目位于不同的数据库等。此外,在这个项目中,我计划创建多个数据库,其中包含我要分析的数据的不同部分,只是为了保持整洁。 您应该始终在 INSERT INTO 上使用显式列列表,在 SELECT 查询上使用显式列列表。如果这不能解决问题,请尝试创建一个小的问题重现。 【参考方案1】:

这只是一个潜在的答案,但是……为什么您的函数查询如此复杂?这仅在一个 SELECT 语句中执行相同的操作:

CREATE FUNCTION [Load].[GetH2HRecords]
     (@HomeTeam varchar(50), @AwayTeam varchar(50), @MatchDate date)
RETURNS @H2H TABLE
(
Home int,
Away int,
Draw int
)
AS 

BEGIN

DECLARE @FromDate date
SET @FromDate = DATEADD(yyyy,-10,@MatchDate)
INSERT INTO @H2H
SELECT 
    SUM(
        CASE
            WHEN FTResult = 'H' 
                Then 1
            ELSE 0
        END 
        ) as HomeHTH,
    SUM(
        CASE
            WHEN FTResult = 'A' 
                Then 1
            ELSE 0
        END 
        ) as AwayHTH,
    SUM(
        CASE
            WHEN FTResult = 'D' 
                Then 1
            ELSE 0
        END 
        ) as DrawHTH
FROM MatchData.PremierLeague
WHERE HomeTeam = @HomeTeam 
AND AwayTeam = @AwayTeam
AND MatchDate > @FromDate

RETURN
END

【讨论】:

谢谢 Laughing Vergil,我回家后试试这个。我以易于阅读/简单的方式设置它,因为原始查询计算出每个计数的百分比。由于它不起作用,我决定将其删除,并决定如果我可以将计数放入表中,我将在表中添加一个计算列以显示百分比。我希望有一些明显的问题,这样我就不必像你一样重新编写查询,但也许这是唯一的解决方案。 您可以随时添加一个额外的列 COUNT(*) As Total,并添加一个 AND 子句 - AND FTResult IN ('H', 'A', 'D') - 到查询中,然后在显示层中即时计算百分比,或者在选择时来自临时表。

以上是关于为啥 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能将这些值插入到我添加到此数据库的表中?

试图在我的 SQL 表中插入多行。总是显示 SQL 命令未正确结束 [重复]

插入前的表线轴?

SQLite,在我的表中插入变量(c#控制台应用程序)

Laravel 插入默认值而不是通过请求发送的数据

使用存储过程将数据插入从其他表派生的表中