【问题标题】:SQL many to many grouping onto one rowSQL多对多分组到一行
【发布时间】:2014-01-10 22:31:05
【问题描述】:

我确实使用了搜索,但少数结果似乎没有回答我的具体问题(或者我的 sql 技能不足以将答案应用于我的场景)

我有需要加入的表格。上下文是一个交付业务。一张表包含交付周期时间表。我需要从这张表中获取客户注册每周交货的日期。这是在帐号上加入的。

另一个表包含,帐号,交货日期实例等

我要做的是提取过去 6 周内每个帐号的平均交货次数。但仅适用于开始日期在 6 到 10 周之前的帐户。

我使用的代码似乎恢复了正确的日期范围,但是,我需要每个帐号一行,以及 6 周期间的平均交付次数。我正在使用的代码没有正确执行此操作。

非常感谢任何帮助。

谢谢

select mov.AccountNumber,
sch.contractStart,
mov.TypeOfMovement,
mov.Outlet,
mov.RoundName,
mov.VehicleType,
avg(mov.NumberofItems)


FROM [round_movements]mov  
left outer join [schedule]sch on sch.AccountNumber=
mov.AccountNumber                          
where mov.outlet='County'
and DATEDIFF(week, sch.ContractStart,GETDATE()) in(10,9,8,7,6)
and DATEDIFF(week, mov.RoundDate,GETDATE()) in (6,5,4,3,2,1,0)

group by 
mov.AccountNumber,
mov.RoundName,
sch.contractStart,
mov.TypeOfMovement,
mov.Outlet,
mov.VehicleType,
mov.NumberofItems
order by mov.AccountNumber

上面代码的结果:

 ════════════════════════════════════════════════════════════════════════════════════════╗
║ AccountNumber   contractStart  Outlet   RoundName       VehicleType   Avg  No of Items ║
╠════════════════════════════════════════════════════════════════════════════════════════╣
║ 4000461         27/11/2013    town1     E4 (Wednesday)  sprinter       1               ║
           ║
║ 6382401         29/10/2013    town2     E1 (Thursday)   sprinter       2               ║
║ 6382401         29/10/2013    town2     E1 (Thursday)   sprinter       2               ║
╚════════════════════════════════════════════════════════════════════════════════════════╝

预期结果:

╔═════════════════════════════════════════════════════════════════════════════════════╗
║ AccountNumber   contractStart   Outlet  RoundName      VehicleType Avg No Items     ║
╠═════════════════════════════════════════════════════════════════════════════════════╣
║ 4000461         27/11/2013      town 1  E4 (Wednesday)  sprinter    1               ║
║ 6382401         29/10/2013      town2   E1 (Thursday)   sprinter    2               ║
║            ║
╚═════════════════════════════════════════════════════════════════════════════════════╝ 

Rs 建议进行以下更改后的结果:

╔═════════════════════════════════════════════════════════════════════════════════════╗
║ AccountNumber   contractStart   Outlet  RoundName      VehicleType Avg No Items     ║
╠═════════════════════════════════════════════════════════════════════════════════════╣
║   
  4000461   27/11/2013  Bristol E4 (Wednesday)  RCV 1
  6382401   29/10/2013  Bristol E1 (Thursday)   RCV 2
  6382401   29/10/2013  Bristol E1 (Thursday)   RCV 2

          ║
╚═════════════════════════════════════════════════════════════════════════════════════╝ 

【问题讨论】:

  • 按 AccountNUMer、contractStart、outlet、roundname 分组
  • 我添加了 sql-server 标签,因为查询语法强烈建议使用 SQL Server。
  • 对不起。我正在使用 SQL Server 2008 R2。谢谢。
  • 从按列分组的列表中删除 mov.NumberofItems
  • 谢谢rs。我尝试删除它,但每个帐号仍有多行:(

标签: sql sql-server join group-by


【解决方案1】:

试试这个,从分组列表中删除mov.NumberofItems

select mov.AccountNumber,
sch.contractStart,
mov.TypeOfMovement,
mov.Outlet,
mov.RoundName,
mov.VehicleType,
avg(mov.NumberofItems)


FROM [round_movements]mov  
left outer join [schedule]sch on sch.AccountNumber=
mov.AccountNumber                          
where mov.outlet='County'
and DATEDIFF(week, sch.ContractStart,GETDATE()) in(10,9,8,7,6)
and DATEDIFF(week, mov.RoundDate,GETDATE()) in (6,5,4,3,2,1,0)

group by 
mov.AccountNumber,
mov.RoundName,
sch.contractStart,
mov.TypeOfMovement,
mov.Outlet,
mov.VehicleType
order by mov.AccountNumber

【讨论】:

  • 感谢您的快速回复。我从 group by 中删除了项目数,但每个帐号仍然得到多行:(
  • 我在原始问题中添加了 - 如您所见,每个帐号有不止一行 - 它似乎重复了每个帐号的平均项目数。再次感谢您的帮助
  • 基于新结果集的预期结果是什么?目前尚不清楚您尝试按哪些列分组或返回平均数据。是否要返回最短合同开始日期和平均项目?
  • 真的很抱歉,我原来的问题的结果不正确(我认为是旧代码)。我已经更新以显示我的代码产生的内容、您的建议和我需要的内容。我只需要按帐号分组并显示所有日期交付的所有项目的平均值。非常感谢。
【解决方案2】:

我可以看到一些事情会阻止您获得预期的结果。

  1. 您不需要 group by 中的 mov.NumberofItems,因为您正在对其进行平均。
  2. 您需要使用 MIN 函数来提供第一个合同开始日期,例如 min(sch.contractStart),然后您就不需要 group by 中的 sch.contractStart。

这应该会给您预期的结果。

所以你的查询会是这样的。

select 
  mov.AccountNumber,
  min(sch.contractStart),
  mov.TypeOfMovement,
  mov.Outlet,
  mov.RoundName,
  mov.VehicleType,
  avg(mov.NumberofItems)
FROM 
  [round_movements]mov  
  left outer join [schedule]sch on sch.AccountNumber=mov.AccountNumber                          
where 
  mov.outlet='County'
  and DATEDIFF(week, sch.ContractStart,GETDATE()) in(10,9,8,7,6)
  and DATEDIFF(week, mov.RoundDate,GETDATE()) in (6,5,4,3,2,1,0)
group by 
  mov.AccountNumber,
  mov.RoundName,
  mov.TypeOfMovement,
  mov.Outlet,
  mov.VehicleType,
  mov.NumberofItems
order by 
  mov.AccountNumber

【讨论】:

  • 谢谢 - 我的代码与上面相同,但结果仍然如上 - 与 Rs 的建议相同 - 每个帐户不止一行,且平均项目数量重复 :( 真的很烦人抱歉跨度>
  • Rs 的建议不包括合同开始日期的 min(sch.contractStart)。
  • 您获得额外行的原因是因为日期不相同,因此您会为每个行获得单独的行
  • 当我使用 min() 时,结果是一样的,因为每个账户只有一个合同开始日期。有多个回合日期,但只有一个合同开始日期
【解决方案3】:

附加到其他人所说的内容:

您获得多个结果的原因是 sch.contractStart 对于 2 个记录的 2 个帐号是不同的。
您可以做的是将sch.contractStart 包裹在MAX() 中并将其从GROUP BY 中删除。这将为您提供特定帐号的最新合同开始日期,我认为从逻辑角度来看这是有道理的。

编辑 - 在 OP 的问题编辑之后
我可以看到更新的结果,有 2 条完全相同的记录。 你可以把整个东西包装成SELECT DISTINCT 消除它。但这不是正确的方法。

实际上,如果所有内容都在 group by 或聚合函数中,我看不出有任何重复记录的原因。 你是否从GROUP BY 中删除了mov.NumberofItems

【讨论】:

  • 同时从GROUP BY 中删除mov.NumberofItems。它已经包含在聚合函数中
  • 谢谢。我认为当我运行原始代码时数据集有错误。当我重新运行时,每个帐号只有一个合同开始日期。我已经用这个更新了我原来的问题..抱歉让你更难了
猜你喜欢
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-26
  • 1970-01-01
  • 2013-12-11
  • 2016-03-11
相关资源
最近更新 更多