【问题标题】:How to use group by only for some columns in sql Query?如何仅对sql Query中的某些列使用group by?
【发布时间】:2015-10-12 14:38:13
【问题描述】:

以下查询返回 550 条记录,然后我通过 linq 按控制器中的某些列对其进行分组。但是,如何在 SQL 查询本身中实现“分组依据”逻辑?此外,分组后,我只需要向用户显示 150 个结果。

当前 SQL 查询:

SELECT DISTINCT 
  l.Id AS LoadId
  , l.LoadTrackingNumber AS LoadDisplayId
  , planningType.Text AS PlanningType
  , loadStatus.Id AS StatusId
  , loadWorkRequest.Id AS LoadRequestId
  , loadStatus.Text AS Status
  , routeIds.RouteIdentifier AS RouteName
  , planRequest.Id AS PlanId 
  , originPartyRole.Id AS OriginId
  , originParty.Id AS OriginPartyId
  , originParty.LegalName AS Origin
  , destinationPartyRole.Id AS DestinationId
  , destinationParty.Id AS DestinationPartyId
  , destinationParty.LegalName AS Destination
  , COALESCE(firstSegmentLocation.Window_Start, originLocation.Window_Start) AS StartDate
  , COALESCE(firstSegmentLocation.Window_Start, originLocation.Window_Start) AS BeginDate
  , destLocation.Window_Finish AS EndDate
    AS Number
    FROM Domain.Loads (NOLOCK) AS l
    INNER JOIN dbo.Lists (NOLOCK) AS loadStatus ON l.LoadStatusId = loadStatus.Id
    INNER JOIN Domain.Routes (NOLOCK) AS routeIds ON routeIds.Id = l.RouteId

    INNER JOIN Domain.BaseRequests (NOLOCK) AS loadWorkRequest ON loadWorkRequest.LoadId = l.Id 
    INNER JOIN Domain.BaseRequests (NOLOCK) AS planRequest ON planRequest.Id = loadWorkRequest.ParentWorkRequestId
    INNER JOIN Domain.Schedules AS planSchedule ON planSchedule.Id = planRequest.ScheduleId

    INNER JOIN Domain.Segments (NOLOCK) os on os.RouteId = routeIds.Id AND os.[Order] = 0
    INNER JOIN Domain.LocationDetails (NOLOCK) AS originLocation ON originLocation.Id = os.DestinationId
    INNER JOIN dbo.EntityRoles (NOLOCK) AS originPartyRole ON originPartyRole.Id = originLocation.DockRoleId
    INNER JOIN dbo.Entities (NOLOCK) AS originParty ON originParty.Id = originPartyRole.PartyId

    INNER JOIN Domain.LocationDetails (NOLOCK)  AS destLocation ON destLocation.Id = routeIds.DestinationFacilityLocationId  
    INNER JOIN dbo.EntityRoles (NOLOCK)  AS destinationPartyRole ON destinationPartyRole.Id = destLocation.DockRoleId
    INNER JOIN dbo.Entities (NOLOCK)  AS destinationParty ON destinationParty.Id = destinationPartyRole.PartyId

    INNER JOIN dbo.TransportationModes (NOLOCK) lictm on lictm.Id = l.LoadInstanceCarrierModeId
    INNER JOIN dbo.EntityRoles  (NOLOCK) AS carrierPartyRole ON lictm.CarrierId = carrierPartyRole.Id 
    INNER JOIN dbo.Entities  (NOLOCK) AS carrier ON carrierPartyRole.PartyId = carrier.Id 

    INNER JOIN dbo.EntityRoles  (NOLOCK) AS respPartyRole ON l.ResponsiblePartyId = respPartyRole.Id 
    INNER JOIN dbo.Entities  (NOLOCK) AS respParty ON respPartyRole.PartyId = respParty.Id 
    INNER JOIN Domain.LoadOrders (NOLOCK) lo ON lo.LoadInstanceId = l.Id 
    INNER JOIN Domain.Orders  (NOLOCK) AS o ON lo.OrderInstanceId = o.Id

    INNER JOIN Domain.BaseRequests  (NOLOCK) AS loadRequest ON loadRequest.LoadId = l.Id 

    --Load Start Date
    LEFT JOIN Domain.Segments (NOLOCK) AS segment ON segment.RouteId = l.RouteId AND segment.[Order] = 0
    LEFT JOIN Domain.LocationDetails (NOLOCK) AS firstSegmentLocation ON firstSegmentLocation.Id = segment.DestinationId

    LEFT JOIN dbo.Lists (NOLOCK) AS planningType ON l.PlanningTypeId = planningType.Id

    LEFT JOIN dbo.EntityRoles (NOLOCK)  AS billToRole ON o.BillToId = billToRole.Id
    LEFT JOIN dbo.Entities  (NOLOCK) AS billTo ON billToRole.PartyId = billTo.Id                     

 WHERE o.CustomerId in (34236) AND originLocation.Window_Start >= '07/19/2015 00:00:00' AND originLocation.Window_Start < '07/25/2015 23:59:59' AND l.IsHistoricalLoad = 0
AND loadStatus.Id in (285, 286,289,611,290)
AND loadWorkRequest.ParentWorkRequestId IS NOT NULL
AND routeIds.RouteIdentifier IS NOT NULL
AND (planSchedule.EndDate IS NULL OR (planSchedule.EndDate is not null and CAST(CONVERT(varchar(10), planSchedule.EndDate,101) as datetime) > CAST(CONVERT(varchar(10),GETDATE(),101) as datetime))) ORDER BY l.Id DESC

linq:

//Get custom grouped data
var loadRequest = (from lq in returnList
                        let loadDisplayId = lq.LoadDisplayId
                        let origin = lq.OriginId //get this  origin for route
                        let destination = lq.DestinationId // get this destination for route
                   group lq by new
                   {
                       RouteId = lq.RouteName,
                       PlanId = lq.PlanId,
                       Origin = lq.OriginId,
                       Destination = lq.DestinationId
                   }
                   into grp
                   select new
                   {
                       RouteId = grp.Key.RouteId,
                       PlanId = grp.Key.PlanId,
                       Origin = grp.Key.Origin,
                       Destination = grp.Key.Destination,
                       Loads = (from l in grp select l)
                   }).OrderBy(x => x.Origin).ToList();

【问题讨论】:

  • 你到底想在这里做什么?能否提供样本数据和预期结果?
  • 向我们展示您正在寻找的示例。如果您有两个不同的行,Column1='A',但 Column2 和 3 的值不同,应该返回什么?
  • @vignesh:你想达到什么目标?你能分享你寻找的输入和输出吗?您还需要有一些聚合函数才能使用 group by
  • 你想通过按列离开其他组来达到什么目的
  • 我们需要查看您的示例表

标签: sql sql-server sql-server-2008 c#-4.0 group-by


【解决方案1】:

关于GROUP BY,您需要了解的重要一点是,您必须假设GROUP BY 列表之外的每一列中都有多个值。在您的情况下,您必须假设Column1 的每个值都会有Column2Column3 的多个值,它们都被视为一个组。

如果您希望查询处理这些列中的任何一个,则必须指定如何处理这些多个值。

以下是您的一些选择:

  • 为组中的列选择最小值或最大值 - 为此使用 MIN(...)MAX(...) 聚合器
  • 计算组中非NULL 的项目 - 使用COUNT(...)
  • 在组中产生非NULL 值的平均值 - 使用AVG(...)

例如,如果您想针对Column1 的每个值查找最小的Column2 和平均Column3,您的查询将如下所示:

select 
    Column1, MIN(Column2), AVG(Column3)
from 
    TableName 
group by 
    Column1

【讨论】:

    【解决方案2】:

    我猜您想按第 1 列分组,但在您的选择中包含第 2 列和第 3 列。使用 Group By 你不能这样做。但是,您可以通过使用 OVER() 运算符的 T-SQL 窗口化函数来执行此操作。由于您没有说要如何聚合,因此我无法提供示例。但是看看 T-SQL 窗口函数。这个article 可能会帮助您入门。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 2012-02-05
      • 2021-02-14
      • 1970-01-01
      相关资源
      最近更新 更多