有关聚合函数或FOR XML路径查询中的group by子句的错误

时间:2017-06-14 08:26:27

标签: sql-server

这个领域已经给出了几个答案,但我想了解如何解决这个问题,当它是FOR XML Path的一部分时。

我想根据RegionID连接所有差异。我只在regionID上使用group by,但是我收到一个错误,说disppancy.description需要是聚合的一部分(使用像MAX这样的东西会扭曲我的数据),并且在group by子句中包含discrepancy.description也不准确。

<<<添加了整个查询以进一步说明>>>

select top 100
lpr.RegionID,
lpr.Region, 
Max(la.LeftOffWt),
isnull(stuff((select distinct ','+coalesce(discrepancy.description,'NA')
                 from disConsignment as discrepancy
                     inner join whsHeader as wh
                         on wh.WhsHeaderID = discrepancy.WhsHeaderID
                     inner join whsConsignment as wc
                         on wc.whsHeaderID = wh.WhsHeaderID
                     inner join cgtConsignment as c
                         on c.[Consignment Reference] = wc.ConsignmentReference
                     inner join movMovement as m
                         on m.MovementID = wh.RunMovID
                     inner join dbo.genAddress as ga
                         on ga.AddressID = c.Consignor
                     inner join dbo.lstPostcode as lp
                         on lp.Postcode = ga.PostcodePrefix
                     inner join dbo.lstPostcodeRegion as lpr
                         on lpr.RegionID = lp.RegionID
                            and c.Cancelled = 0
                            and discrepancy.WhsHeaderID = wc.whsHeaderID
                 where wc.whsHeaderID = wh.whsHeaderID
                       and wc.StatusCode = 'NL'
                       and wh.ArrDepDate between @StartDate and @EndDate
                       and lpr.RegionID = max (lprdiscrepancy.RegionID)
                 for xml path('')
                ),1,1,''),'') as [Not Collected]
   from movmovement m 
  inner join whsHeader wh on wh.RunMovID = m.MovementID
  Inner join whsConsignment wc on wc.whsHeaderID = wh.WhsHeaderID
  inner join cgtConsignment c on c.[Consignment Reference] = wc.ConsignmentReference
  INNER JOIN dbo.genAddress ga ON ga.AddressID = c.Consignor
  INNER JOIN dbo.lstPostcode lp ON lp.Postcode = ga.PostcodePrefix
  INNER JOIN dbo.lstPostcodeRegion lpr ON lpr.RegionID = lp.RegionID
  inner join disConsignment dc on dc.ConsignmentRef = c.[Consignment Reference]
  Left join (SELECT lpr.RegionID, discrepancy.Description
                   FROM  disConsignment discrepancy
                   inner join whsHeader wh on wh.WhsHeaderID = discrepancy.WhsHeaderID
                   inner join whsConsignment wc on wc.whsHeaderID = wh.WhsHeaderID
                    inner join cgtConsignment c on c.[Consignment Reference] = wc.ConsignmentReference
                    INNER JOIN dbo.genAddress ga ON ga.AddressID = c.Consignor
                    INNER JOIN dbo.lstPostcode lp ON lp.Postcode = ga.PostcodePrefix
                    INNER JOIN lstPostcodeRegion lpr ON lpr.RegionID = lp.RegionID
                            AND c.Cancelled = 0
                            AND discrepancy.WhsHeaderID = wc.whsHeaderID
                  WHERE    wc.whsHeaderID = wh.whsHeaderID
                            AND wc.StatusCode IN ( 'NL' ) 
                            AND lpr.RegionID = lp.RegionID
                            AND wh.ArrDepDate BETWEEN @StartDate AND @EndDate 
                            ) lprdiscrepancy on lprdiscrepancy.RegionID = lpr.RegionID
LEFT JOIN ( SELECT lpr.RegionID,
                        SUM(c.[Chargeable Weight]) AS LeftOffWt
                FROM    dbo.whsConsignment wc
                        INNER JOIN whsHeader wh on wh.WhsHeaderID = wc.whsHeaderID
                        INNER JOIN dbo.cgtConsignment c ON c.[Consignment Reference] = wc.ConsignmentReference
                        INNER JOIN dbo.genAddress ga ON ga.AddressID = c.Consignor
                        INNER JOIN dbo.lstPostcode lp ON lp.Postcode = ga.PostcodePrefix
                        INNER JOIN dbo.lstPostcodeRegion lpr ON lpr.RegionID = lp.RegionID
                                                          AND c.Cancelled = 0
                WHERE   StatusCode IN ( 'NL' ) and wh.ArrDepDate between @StartDate and @EndDate
                GROUP BY lpr.RegionID
              ) la ON la.RegionID = lp.RegionID

                      group by lpr.regionID, lpr.Region

                      ORDER BY lpr.RegionID

1 个答案:

答案 0 :(得分:2)

由于提供给脚本的for xml部分的数据位于子查询中,因此会针对主查询中返回的每一行运行该数据。因为它是为每一行运行的,所以您可以在子选择中引用这些值。这意味着您不需要group by,而应将其更改为仅引用主查询中的RegionID列:

select isnull(stuff((select distinct
                            ','+coalesce(discrepancy.description,'NA')
                     from disConsignment as discrepancy
                         inner join whsHeader as wh
                             on wh.WhsHeaderID = discrepancy.WhsHeaderID
                         inner join whsConsignment as wc
                             on wc.whsHeaderID = wh.WhsHeaderID
                         inner join cgtConsignment as c
                             on c.[Consignment Reference] = wc.ConsignmentReference
                         inner join movMovement as m
                             on m.MovementID = wh.RunMovID
                         inner join dbo.genAddress as ga
                             on ga.AddressID = c.Consignor
                         inner join dbo.lstPostcode as lp
                             on lp.Postcode = ga.PostcodePrefix
                         inner join dbo.lstPostcodeRegion as lpr
                             on lpr.RegionID = lp.RegionID
                                and c.Cancelled = 0
                                and discrepancy.WhsHeaderID = wc.whsHeaderID
                     where wc.whsHeaderID = wh.whsHeaderID
                           and wc.StatusCode = 'NL'
                           and wh.ArrDepDate between @StartDate and @EndDate
                           and lpr.RegionID = <RegionID in your main query>
                     for xml path('')
                    ),1,1,''),'') as [Not Collected];

回应以下评论:

with cte as
(
    select lpr.RegionID
          ,lpr.Region
          ,sum(c.[Chargeable Weight]) as LeftOffWt
    from dbo.whsConsignment as wc
        inner join whsHeader as wh
            on wh.WhsHeaderID = wc.whsHeaderID
        inner join dbo.cgtConsignment as c
            on c.[Consignment Reference] = wc.ConsignmentReference
        inner join dbo.genAddress as ga
            on ga.AddressID = c.Consignor
        inner join dbo.lstPostcode as lp
            on lp.Postcode = ga.PostcodePrefix
        inner join dbo.lstPostcodeRegion as lpr
            on lpr.RegionID = lp.RegionID
                and c.Cancelled = 0
        where StatusCode in('NL')
            and wh.ArrDepDate between @StartDate and @EndDate
        group by lpr.RegionID
                ,lpr.Region
)
select cte.RegionID
    ,cte.Region
    ,cte.LeftOffWt
    ,isnull(stuff((select distinct ',' + coalesce(d.description,'NA')
                    from disConsignment as d
                        inner join whsHeader as wh
                            on wh.WhsHeaderID = d.WhsHeaderID
                        inner join whsConsignment as wc
                            on wc.whsHeaderID = wh.WhsHeaderID
                        inner join cgtConsignment as c
                            on c.[Consignment Reference] = wc.ConsignmentReference
                        inner join movMovement as m
                            on m.MovementID = wh.RunMovID
                        inner join dbo.genAddress as ga
                            on ga.AddressID = c.Consignor
                        inner join dbo.lstPostcode as lp
                            on lp.Postcode = ga.PostcodePrefix
                        inner join dbo.lstPostcodeRegion as lpr
                            on lpr.RegionID = lp.RegionID
                                and c.Cancelled = 0
                                and d.WhsHeaderID = wc.whsHeaderID
                    where wc.whsHeaderID = wh.whsHeaderID
                        and wc.StatusCode = 'NL'
                        and wh.ArrDepDate between @StartDate and @EndDate
                        and lpr.RegionID = cte.RegionID
                    for xml path('')
                    ),1,1,''),'') as [Not Collected]
from cte;