如何仅对 sql 查询中的某些列使用 group by?

How to use group by only for some columns in sql Query?

以下查询 returns 550 条记录,然后我通过 linq 按控制器中的某些列对这些记录进行分组。但是,如何在 SQL 查询本身中实现 ​​"group by" 逻辑?此外,post-分组,我只需要向用户显示 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();

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

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

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

以下是您的一些选择:

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

例如,如果您想为 Column1 的每个值找到最小的 Column2Column3 的平均值,您的查询将如下所示:

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