Sql 正在返回计数为0的列
我有一个查询,根据文档的部门和状态查找文档列表Sql 正在返回计数为0的列,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个查询,根据文档的部门和状态查找文档列表 DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5'; DECLARE @DepartmentId NVARCHAR(2) = 'IT'; SELECT ILDPST.name, COUNT(*) AS TodayCount FROM dbo.TableA ILDP LEFT JOIN dbo.TableB ILDPS ON ILDPS.IntranetLoanDealPreStateId =
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE @DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.name,
COUNT(*) AS TodayCount
FROM dbo.TableA ILDP
LEFT JOIN dbo.TableB ILDPS ON ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId
LEFT JOIN dbo.TableC ILDPST ON ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId
WHERE (ILDP.CreatedByDepartmentId = @DepartmentId OR @DepartmentId IS NULL)
AND ILDPS.CurrentStateTypeId IN (
SELECT value
FROM dbo.StringAsIntTable(@StatusIds)
)
GROUP BY ILDPST.name;
这将返回结果:
但是,我也希望能够返回今日计数
等于0的状态(即,无论今日计数
,都应返回id包含在@StatusIds
中的任何状态)
我曾尝试与一些工会/会员/CTE打交道,但我无法完全让它发挥作用。我不太喜欢SQL,所以不确定还能提供什么有用的东西
谢谢 您可以使用以下函数为您的状态id创建一个表值
CREATE FUNCTION [dbo].[SplitString]
(
@myString varchar(max),
@deliminator varchar(2)
)
RETURNS
@ReturnTable TABLE
(
[Part] [varchar](max) NULL
)
AS
BEGIN
Declare @iSpaces int
Declare @part varchar(max)
--initialize spaces
Select @iSpaces = charindex(@deliminator,@myString,0)
While @iSpaces > 0
Begin
Select @part = substring(@myString,0,charindex(@deliminator,@myString,0))
Insert Into @ReturnTable(Part)
Select @part
Select @myString = substring(@mystring,charindex(@deliminator,@myString,0)+ len(@deliminator),len(@myString) - charindex(' ',@myString,0))
Select @iSpaces = charindex(@deliminator,@myString,0)
end
If len(@myString) > 0
Insert Into @ReturnTable
Select @myString
RETURN
END
现在可以将其用作一个表,您可以将其保留到该表中
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
SELECT * FROM dbo.SplitString(@StatusIds, ',')
您可以使用以下函数为您的状态id创建一个表值
CREATE FUNCTION [dbo].[SplitString]
(
@myString varchar(max),
@deliminator varchar(2)
)
RETURNS
@ReturnTable TABLE
(
[Part] [varchar](max) NULL
)
AS
BEGIN
Declare @iSpaces int
Declare @part varchar(max)
--initialize spaces
Select @iSpaces = charindex(@deliminator,@myString,0)
While @iSpaces > 0
Begin
Select @part = substring(@myString,0,charindex(@deliminator,@myString,0))
Insert Into @ReturnTable(Part)
Select @part
Select @myString = substring(@mystring,charindex(@deliminator,@myString,0)+ len(@deliminator),len(@myString) - charindex(' ',@myString,0))
Select @iSpaces = charindex(@deliminator,@myString,0)
end
If len(@myString) > 0
Insert Into @ReturnTable
Select @myString
RETURN
END
现在可以将其用作一个表,您可以将其保留到该表中
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
SELECT * FROM dbo.SplitString(@StatusIds, ',')
如果您想拥有TableC中的所有记录,您需要将所有其他表左键连接到它,而不是将它左键连接到其他表。另外,最好将从
@StatusIds
中创建的筛选表内部联接
,而不是通过子句中的应用它。试试这个:
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE @DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.Name, COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM (SELECT DISTINCT value FROM dbo.StringAsIntTable(@StatusIds)) StatusIds
INNER JOIN dbo.TableC ILDPST
ON ILDPST.IntranetLoanDealPreStateTypeId = StatusIds.value
LEFT JOIN dbo.TableB ILDPS
ON ILDPS.CurrentStateTypeId = ILDPST.IntranetLoanDealPreStateTypeId
LEFT JOIN dbo.TableA ILDP
ON ILDP.IntranetLoanDealPreStateId = ILDPS.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = @DepartmentId OR @DepartmentId IS NULL)
GROUP BY ILDPST.Name;
如果您想拥有TableC中的所有记录,您需要将所有其他表左键连接到它,而不是将它左键连接到其他表。另外,最好将从@StatusIds
中创建的筛选表内部联接
,而不是通过
子句中的应用它。试试这个:
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE @DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.Name, COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM (SELECT DISTINCT value FROM dbo.StringAsIntTable(@StatusIds)) StatusIds
INNER JOIN dbo.TableC ILDPST
ON ILDPST.IntranetLoanDealPreStateTypeId = StatusIds.value
LEFT JOIN dbo.TableB ILDPS
ON ILDPS.CurrentStateTypeId = ILDPST.IntranetLoanDealPreStateTypeId
LEFT JOIN dbo.TableA ILDP
ON ILDP.IntranetLoanDealPreStateId = ILDPS.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = @DepartmentId OR @DepartmentId IS NULL)
GROUP BY ILDPST.Name;
请尝试以下方法:
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE @DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.name,
COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM
dbo.TableC ILDPST
LEFT JOIN
dbo.TableB ILDPS ON ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId
LEFT JOIN
dbo.TableA ILDP ON ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = @DepartmentId OR @DepartmentId IS NULL)
WHERE
ILDPST.IntranetLoanDealPreStateTypeId
IN (
SELECT value
FROM dbo.StringAsIntTable(@StatusIds)
)
GROUP BY ILDPST.name;
请尝试以下方法:
DECLARE @StatusIds NVARCHAR(MAX) = '1,2,3,4,5';
DECLARE @DepartmentId NVARCHAR(2) = 'IT';
SELECT ILDPST.name,
COUNT(ILDP.IntranetLoanDealPreStateId) AS TodayCount
FROM
dbo.TableC ILDPST
LEFT JOIN
dbo.TableB ILDPS ON ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId
LEFT JOIN
dbo.TableA ILDP ON ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId
AND (ILDP.CreatedByDepartmentId = @DepartmentId OR @DepartmentId IS NULL)
WHERE
ILDPST.IntranetLoanDealPreStateTypeId
IN (
SELECT value
FROM dbo.StringAsIntTable(@StatusIds)
)
GROUP BY ILDPST.name;
它未经测试,但请尝试一下:
;With Cte ( Value ) As
( Select Distinct Value From dbo.StringAsIntTable( @StatusIds ) )
Select
ILDPST.name,
COUNT(*) AS TodayCount
From
dbo.TableC As ILDPST
Inner Join Cte On ( ILDPST.IntranetLoanDealPreStateTypeId = Cte.Value )
Left Join dbo.TableB As ILDPS On ( ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId )
Left Join dbo.TableA As ILDP On ( ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId )
And ( ( ILDP.CreatedByDepartmentId = @DepartmentId ) Or ( @DepartmentId Is Null ) )
Group By
ILDPST.name
它未经测试,但请尝试一下:
;With Cte ( Value ) As
( Select Distinct Value From dbo.StringAsIntTable( @StatusIds ) )
Select
ILDPST.name,
COUNT(*) AS TodayCount
From
dbo.TableC As ILDPST
Inner Join Cte On ( ILDPST.IntranetLoanDealPreStateTypeId = Cte.Value )
Left Join dbo.TableB As ILDPS On ( ILDPST.IntranetLoanDealPreStateTypeId = ILDPS.CurrentStateTypeId )
Left Join dbo.TableA As ILDP On ( ILDPS.IntranetLoanDealPreStateId = ILDP.IntranetLoanDealPreStateId )
And ( ( ILDP.CreatedByDepartmentId = @DepartmentId ) Or ( @DepartmentId Is Null ) )
Group By
ILDPST.name
对于@StatusIds
,哪个表中没有相应的记录?您已经在进行外部联接,因此应该没有问题,除非是导致记录被排除的TableA
,在这种情况下,您需要在联接中对表重新排序。注意:(ILDP.CreatedByDepartmentId=@DepartmentId或@DepartmentId为NULL)
可以写成(ILDP.CreatedByDepartmentId=IsNull)(@DepartmentId,ILDP.CreatedByDepartmentId)
@shadow我不建议这样做,它会稍微慢一点performance@t-clausen.dk非常正确!刚刚在一个包含303.423行的表上进行了测试。with-IsNull结果在~10“中返回,with-or-xxx在~3”中为null。谢谢朋友。哪个表中没有@StatusIds
的相应记录?您已经在外部联接,因此应该可以,除非是TableA
导致记录被排除,在这种情况下,您需要在联接中对表重新排序。注意:(ILDP.CreatedByDepartmentId=@DepartmentId或@DepartmentId为NULL)
可以写成(ILDP.CreatedByDepartmentId=IsNull(@DepartmentId,ILDP.CreatedByDepartmentId)
@shadow我不建议这样做,它会稍微慢一点performance@t-clausen.dk非常正确!刚刚在一个包含303.423行的表上进行了测试。在~10“中返回IsNull结果,在~3”中返回with或xxx为null。感谢朋友。我相信他们已经在dbo.StringAsIntTable
name.:-)下使用了此函数啊,是的,错过了。谢谢。我相信他们已经在dbo.StringAsIntTable
name.:-)下使用了这个函数。啊,是的,错过了。谢谢。你不能有一个左连接并在WHERE子句中为该连接的表设置一个条件。它取消左连接,使其成为一个内部连接(除非@DepartmentId为NULL)@t-clausen.dk请注意,这个条件出现在ON
子句中。根本没有WHERE
子句。我不知道我是怎么误解的,我的道歉。不过还有一些其他问题。COUNT(ILDP,*)无效,nvarchar状态ID中的重复项将导致重复data@t-clausen.dk您是对的。谢谢。添加到答案中。您不能有左连接并在WHERE子句中为该连接表设置条件。它会取消左连接,使其成为内部连接(当@DepartmentId为NULL时除外)@t-clausen.dk请注意,这个条件出现在ON
子句中。根本没有WHERE
子句。我不知道我是怎么误解的,我的道歉。不过还有一些其他问题。COUNT(ILDP,*)无效,nvarchar状态ID中的重复项将导致重复data@t-clausen.dk你说得对。谢谢。添加到答案中。CTE是个好主意,但我相信它仍然必须在From
或Join
子句中明确提到。@Y.B.它与tabledbo.TableB
连接。而不是在e xxx in(select..)
。正如@Y.B.正确地说的那样,如果不引用CTE中的列,就不能像使用普通表(FROM或JOIN)一样引用CTE中的列@t-clausen.dk Jesusss…现在我看到了问题所在。真是个蠢货!谢谢各位。我会在脚本中更正它。@shadow-Cte筛选将被LEFT JOIN
禁用。正如@t-clausen.dk之前对我的答案所评论的那样,@statusID中可能存在重复项,这些重复项在原始解决方案中没有效果,但在JOIN
。CTE是个好主意,但我相信它仍然必须在From
或JOIN
子句中明确提到。@Y.B.它与tabledbo.TableB
连接。而不是使用where xxx in(选择..)
。正如@Y.B.正确地说的,如果不引用CTE中的列,就不能像使用普通表(FROM或JOIN)一样引用它@t-clausen.dk Jesusss…现在我看到了问题所在。真是个蠢货!谢谢各位。我会在脚本中更正它。@shadow-Cte筛选将被LEFT JOIN
禁用。正如@t-clausen.dk之前对我的答案所评论的那样,@statusID中可能存在重复项,这些重复项在原始解决方案中没有效果,但在JOIN
@Y.B.你完全正确,这一点已经得到纠正,我很高兴ashamed@Y.B.你完全正确,这已经纠正了,我感到羞愧