Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server组记录和计数具有类似名称的总数_Sql_Sql Server - Fatal编程技术网

SQL Server组记录和计数具有类似名称的总数

SQL Server组记录和计数具有类似名称的总数,sql,sql-server,Sql,Sql Server,我试图计算每个用户打开的日志记录的总数。 我的问题是用户名有三个不同的前缀。CC YY或无。 我可以替换使名称相同的前缀,但用这个修改过的名称对它们进行分组时遇到了问题。数据分布在三个表中,我需要排除已关闭和不活动的记录 这个简化的查询返回我想要的未分组结果的示例 select sname ,( Select count(lDiaryHeaderID) FROM DiaryHeader inner join OwnersCorporation on lObjectID = l

我试图计算每个用户打开的日志记录的总数。 我的问题是用户名有三个不同的前缀。CC YY或无。 我可以替换使名称相同的前缀,但用这个修改过的名称对它们进行分组时遇到了问题。数据分布在三个表中,我需要排除已关闭和不活动的记录

这个简化的查询返回我想要的未分组结果的示例

select sname 
 ,( Select count(lDiaryHeaderID)
    FROM DiaryHeader
    inner join OwnersCorporation on lObjectID = lOwnersCorporationID
    where 
    sObjectType = 'B' 
    AND DiaryHeader.bRecordClosed = 'N'
    AND DiaryHeader.dActionDueDate < cast (GETDATE() as DATE)
    AND OwnersCorporation.bManaged  = 'Y'
    AND tbluser.lUserID = strata.dbo.OwnersCorporation.lUserID 
  ) as TotalOverDue

FROM tblUser 
WHERE bActive = 'Y'
AND bManager = 'Y'
ORDER by sName
我要做的是从名称中删除CC和YS前缀 并将它们分组为单个条目,然后将总数相加

期望结果

sname               TotalOverDue
Belinda Smith       574
Julie Brown         462
Kris White          0
Sharon Towell       38
Colleen Black       131
Jessica Jones       166
Joanne Beigh        305
我想到了这个

select Replace(Replace(sName, 'CC ',''), 'YS ','')    
 ,( Select count(lDiaryHeaderID)    
    FROM DiaryHeader    
    inner join OwnersCorporation on lObjectID = lOwnersCorporationID    
    where     
    sObjectType = 'B'    
    AND DiaryHeader.bRecordClosed = 'N'    
    AND DiaryHeader.dActionDueDate < cast (GETDATE() as DATE)    
    AND OwnersCorporation.bManaged  = 'Y'    
    AND tbluser.lUserID = strata.dbo.OwnersCorporation.lUserID     
  ) as TotalOverDue    

FROM tblUser     
WHERE bActive = 'Y'    
AND bManager = 'Y'    
group by sName
然而,我得到了这个错误消息

列“tblUser.lUserID”在选择列表中无效,因为它既不包含在聚合函数中,也不包含在GROUP BY子句中

如果我把lUserID放在groupby子句中,它只会像预期的那样显示重复的用户名

你知道我哪里做错了,该怎么做吗。 谢谢 大卫

更新:

我的实际解决方案有多个列,为了简化我的问题,我删除了其中两列。现在,我试图再次扩展它,我遇到了更多的问题

下面是我将另外两列添加回的尝试。今天到期,但我的总数正在滚雪球

更新2 多亏菲利普的鹰眼。他发现了一些剪切粘贴错误,这段代码现在返回所需的结果。 感谢所有人,他们给出了一些非常有趣和多样化的解决方案。我将坚持第一个有效的方法:

    select Replace(Replace(sName, 'CC ', ''), 'YS ', ''),
    coalesce(sum(od.cnt), 0) as TotalOverDue,
    coalesce(sum(dt.cnt), 0) as DueToday,
    coalesce(sum(td.cnt), 0) as TotalDue

from tblUser u

left join (
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        and dh.dActionDueDate < cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) od on u.lUserID = od.lUserID

left join (
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        and dh.dActionDueDate = cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) dt on u.lUserID = dt.lUserID

left join (
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        --and dh.dActionDueDate < cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) td on u.lUserID = td.lUserID

where bActive = 'Y'
and bManager = 'Y'
group by Replace(Replace(sName, 'CC ', ''), 'YS ', '')

首先,您需要使用replace表达式而不是列sName进行分组。另外,要小心替换,因为它会替换字符串中任何位置的匹配项

其次,用左连接替换相关子查询

select Replace(Replace(sName, 'CC ', ''), 'YS ', ''),
    coalesce(sum(od.cnt), 0) as TotalOverDue
from tblUser u
left join (
    select oc.lUserID,
        count(ldhID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = locID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        and dh.dActionDueDate < cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) od on u.lUserID = od.lUserID
where bActive = 'Y'
    and bManager = 'Y'
group by Replace(Replace(sName, 'CC ', ''), 'YS ', '')

您可以像这样使用Replace,然后根据需要分组:

declare @CC varchar(20)
declare @YS varchar(20)
Set @CC = 'CC sample name'
Set @YS = 'CC sample name'
select replace(@CC,'CC ',''),replace(@YS,'YS ','');

下面是我的推荐

我使用大小写表达式检查名称是否以CC或YS开头,如果是,请删除前3个字母。这可确保名称本身中存在的任何CC/Y(例如,作为首字母)不会像替换函数那样被无意中删除

SELECT 
    tblUserNameNormalized.sNameNormalized 
  , COALESCE(SUM(od.cnt), 0) AS TotalOverDue 
  , COALESCE(SUM(dt.cnt), 0) AS DueToday 
  , COALESCE(SUM(td.cnt), 0) AS TotalDue 
FROM 
  ( 
      SELECT 
          lUserID
        , CASE 
          -- Check if the name starts with CC or YS, and skip the first 3 letters in that case 
          WHEN sName LIKE ('CC%') THEN SUBSTRING(sName, 4, LEN(sName) - 3) 
          WHEN sName LIKE ('YS%') THEN SUBSTRING(sName, 4, LEN(sName) - 3) 
          -- Else use the name as-is 
          ELSE sName 
          END AS sNameNormalized 
      FROM 
        tblUser 
      WHERE bActive = 'Y'
        AND bManager = 'Y'
  ) as tblUserNameNormalized 
  LEFT JOIN ( 
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        and dh.dActionDueDate < cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
  ) od on tblUserNameNormalized.lUserID = od.lUserID
  LEFT JOIN (
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        and dh.dActionDueDate = cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) dt on tblUserNameNormalized.lUserID = dt.lUserID
  LEFT JOIN (
    select oc.lUserID,
    count(lDiaryHeaderID) cnt
    from DiaryHeader dh
    inner join OwnersCorporation oc on lObjectID = lOwnersCorporationID
    where sObjectType = 'B'
        and dh.bRecordClosed = 'N'
        --and dh.dActionDueDate < cast(GETDATE() as date)
        and oc.bManaged = 'Y'
    group by oc.lUserID
    ) td on tblUserNameNormalized.lUserID = td.lUserID 
GROUP BY tblUserNameNormalized.sNameNormalized 

是的,它会给出错误,因为在代码中您使用的GROUPBY子句没有out AGGRATE函数

请尝试下面的脚本

选择a.sName,将SumtotalAbout作为TotalAbout 从…起 选择替换sName、'CC'、'YS'作为sName ,选择countlDiaryHeaderID 从日记头 lObjectID=lOwnersCorporationID上的内部联接所有者公司 哪里 sObjectType='B' 和DiaryHeader.bRecordClosed='N' 和DiaryHeader.dActionDueDate<将GETDATE转换为日期 AND OwnersCorporation.bmmanaged='Y' 和tbluser.lUserID=strata.dbo.OwnersCorporation.lUserID 逾期

    FROM tblUser     
    WHERE bActive = 'Y'    
    AND bManager = 'Y'  ) a

按sName分组

如果我注释掉子查询中的行,并且tbluser.lUserID=strata.dbo.OwnersCorporation.lUserID,则名称现在可以正确分组,但总数当然都是错误的。在该行未注释的情况下,我仍然得到u.lUserID=od上的错误od。lUserID是正确的。u.lUserID=od.lUserID上的dt应更改为u.lUserID=dt.lUserID上的dt。同样,u.lUserID=od.lUserID上的td应该更改为u.lUserID=td.luseridw上的td当您加入嵌套查询时,您已经给出了一个别名,如od、dt、td。但是,它后面的join语句(在u.lUserID=XY.lUserID上进行join)始终将XY作为od,它应该反映相关嵌套查询的别名。看起来我收到了三个正确答案,这是难以置信的。看起来我只能将一个答案标记为正确答案,我实现了@GurV answer,所以他的答案被选中。再次感谢大家。@Phylyp,我感谢你们为回答问题所付出的努力。对重复用户名的要求很快就会取消。事实上,它们仍然存在,是因为我的老板有一项更难解决的工作,那就是告诉我将它们合并到报告中:由于列表中只有十几个左右的用户,获得这样一个用户名的机会很小。令我惊讶的是,有184个婴儿的名字以ys结尾,而这只是男孩的名字。毕竟,我可能不得不做出这样的改变:我只是想了解一下你增加的竞争对手。什么是ldhID和locID,它们都是无效的列名:愚蠢的me lDiaryHeaderID和lOwnersCorporatinID为什么要再次键入它们。顺便说一句,我确实想到了CC和YS,但它们在我的用户名中是独一无二的。@David-这种情况应该没问题。谢谢你的回答,这很有效,但我希望我能学会如何达到这个结果。如果我什么也学不到,我注定会再次犯同样的错误。此外,记录为零的用户显示为空。我知道这个过程
必须处理的数据可能不会像NULL一样。我怎么能返回零呢?别担心,我发现了零的东西,选择Isnull sumod.cnt,0作为totaloverdue谢谢phylip。这也行得通,但我仍然在考虑如何将我的其他两个列包含进去。虽然它漏掉了零records@DavidPollard-很好的一点是零记录,我应该使用外部连接而不是内部连接来连接tblUser。i、 没错,那没什么区别。在tblUser.lUserID=OwnersCorporation上右外连接tblUser。lUserID@DavidPollard-请参阅您问题下方的我的评论,查看其他两列。@DavidPollard-我已根据您给出的修改后的查询(包括这两列)更新了我的查询。谢谢Sudhakar,这也准确地回答了问题,但正如我所提到的,我将问题简化为一列,现在我看不出如何再次添加其他两列。我需要包括今天到期和总到期的记录计数。有什么想法吗?嗨,大卫,根据你的问题,我无法假设你的桌子是如何设计的。请您将表结构与其数据共享,以便我可以运行您的脚本并将其修改为您想要的结果。嗨,Sudhakar,正如我所说,您的答案与问题匹配,因此您的解决方案很好。我收到了三个有效的解决方案,但只能将其中一个作为答案。这是我用的答案,并不是说它比你的答案更好,只是更快。实际的表是复杂的,如果不拿出一堆测试数据,我无法公开数据。事实上,为了保护无辜,我改变了名字:
    FROM tblUser     
    WHERE bActive = 'Y'    
    AND bManager = 'Y'  ) a