为什么SQL计数(*)与SQL Count(数字)存在行为差异



我知道计数(*( - 将返回所有行的总计数,包括nulls。计数(colname( - 将返回所有colname不为null的行的总数。

今天,我的大学之一在SQL中遇到了Count((问题。应用一些日期过滤器后,他试图从视图中获取行数。

查看返回数据结构

 [Year]                 VARCHAR(4)        
,[Month]                VARCHAR(4)        
,AType                  VARCHAR(20)       
,PActualsID             INT               
,EID                    VARCHAR(12)       
,CID                    INT               
,CGId                   INT               
,EMargin                NUMERIC(17,3)     
,Period                 DATETIME          
,PLID                   INT               
,PCID                   INT               
,PSID                   INT               
,VPID                   INT               
,VSID                   INT               
,STID                   INT               

查询1

SELECT * from vw_ActualAllocation_New
where   EntityId = '442105'       and 
        Period   >= '01-Jan-2017' AND  Period  < '01-Jan-2018'

这返回94个记录。

查询2

SELECT Count(*) from vw_ActualAllocation_New
where   EID = '442105'    and 
        Period   >= '01-Jan-2017' AND  Period  < '01-Jan-2018'

这返回错误

msg 241,级别16,状态1,第1行转换时失败 来自字符字符串的日期和/或时间。

查询3

SELECT Count(EMargin) from vw_ActualAllocation_New
where   EID = '442105'    and 
        Period   >= '01-Jan-2017' AND  Period  < '01-Jan-2018'

这使我算作94。

请注意,Emargin是数字数据类型,也是所有其他类型 例如int和varchar返回相同的错误。

请分享您对这两种行为之间区别的想法。

SQL Server环境:Microsoft SQL Server 2012(构建7601:服务包1((HyperVisor(

更新 - 查看代码

CREATE VIEW [dbo].[vw_ActualAllocation_New]
SELECT D.Year, D.Month, A.AType, A.PAID, D.EntityID, D.CustomerID
,B.CGId, SUM(A.EBITRMargin) AS EBITRMargin
,CONVERT(DATETIME,D.Month + '-01-' + D.Year) AS Period, D.PLID, D.PCID
,D.PSID, D.VPID, D.VSID,D.STID 
FROM  dbo.AAllocations AS A 
INNER JOIN dbo.PActuals AS D ON D.PActualsID = A.PActualsID AND D.Active = 1 
INNER JOIN dbo.Customer AS B ON D.CustomerID = B.CustomerID AND D.EntityID = 
B.EntityID 
INNER JOIN dbo.AStatus AS C ON  A.ASID = C.ASID
WHERE (A.Active = 1) AND (C.Active = 1) AND (C.Reference = 'Actuals') AND 
(C.Status = 1)
GROUP BY D.Year, D.Month, A.AType, A.PAID, D.EntityID, D.CustomerID, B.CGId, 
D.PLID, D.PCID, D.PSID, D.VPID, D.VSID, D.STID 

结论更新

得出的结论是 gordon 的建议,如果您觉得自己可能有其他想法,请在此处发布另外,我尝试将数据从视图中使用,换成一个新表格,其工作正常。问题直接从视图访问时发生。视图的生成发生在大量数据中,并且由于其规模巨大和隐私协议而无法在此处发布。感谢您了解我的局限性并帮助我

问题的最有可能的原因是该行的代码:

CONVERT(DATETIME, D.Month + '-01-' + D.Year) AS Period

在SQL Server中,您绝对不应从字符串到日期使用CONVERT(),而无需指定格式或使用标准格式(yyyymmdd是SQL Server首选的,但我认为Yyyyy-mm-dd也可以接受(。p>在SQL Server的较旧版本中,您可以执行:

CONVERT(DATE, d.Year + RIGHT('00' + D.Month, 2) + '01') as period

这种转换将永远工作。在较新版本中,使用datefromparts()

DATEFROMPARTS(d.Year, d.Month, 1) as Period

为什么会发生这种情况?我推测日期格式被解释为DD-MM-Yyyy而不是MM-DD-Yyyy。换句话说,您认为2月1日的是1月2日。

此外,实体" 442105"的周期值都转换为合理的日期。WHERE子句滤除了不良值。问题在于其他实体和问题,正如达米安指出的那样,是在执行引擎中评估值的地方。

最新更新