如何在使用GROUP BY和Aggregates时

时间:2015-10-16 00:30:49

标签: sql sql-server sql-server-2008-r2 pagination

我正在尝试对SQL Server行进行分页。我在网上找到了一些教程,但是我没有掌握每一个细节,这使我在将their examples改编为现有查询时失败了。

教程说明

USE AdventureWorks2008R2
GO
SELECT
  m.RowNr,
  m.SalesOrderID,
  m.SalesOrderDetailID,
  m.OrderQty,
  m.ProductID,
  m.UnitPrice,
  m.LineTotal,
  m.rowguid,
  m.ModifiedDate
FROM
  (
    SELECT
      ROW_NUMBER() OVER(ORDER BY SalesOrderDetailID DESC) AS RowNr,
      SalesOrderID,
      SalesOrderDetailID,
      OrderQty,
      ProductID,
      UnitPrice,
      LineTotal,
      rowguid,
      ModifiedDate
    FROM Sales.SalesOrderDetail AS tbl
  )m
WHERE RowNr BETWEEN 1 AND 10;

我的现有(非分页)查询:

SELECT DISTINCT
  MAX(i.ID) AS ID,
  i.ItemLookupCode,
  MAX(CAST(i.Notes AS varchar(max))) AS Notes,
  MAX(CONVERT(varchar(30), i.Price, 1)) AS Price,
  MAX(i.PictureName) AS PictureName

FROM Item AS i

LEFT JOIN nitroasl_pamtable AS n
  ON i.ID = n.ItemID

WHERE ( i.ID LIKE '%hdmi%' OR i.ItemLookupCode LIKE '%hdmi%' OR i.Notes LIKE '%hdmi%' OR i.Description LIKE '%hdmi%' OR i.ExtendedDescription LIKE '%hdmi%' OR n.ManufacturerPartNumber LIKE '%hdmi%' OR n.PAM_Keywords LIKE '%hdmi%' )
AND ( i.WebItem = 0 AND i.Price > 0 )

GROUP BY i.ItemLookupCode

ORDER BY i.ItemLookupCode ASC;

我的尝试

/* Return Page */
SELECT
  i.RowID,
  MAX(i.ID) AS ID,
  i.ItemLookupCode,
  MAX(CAST(i.Notes AS varchar(max))) AS Notes,
  MAX(CONVERT(varchar(30), i.Price, 1)) AS Price,
  MAX(i.PictureName) AS PictureName
FROM (
  SELECT

    /* The following row is the line that is being blamed by the error */
    ROW_NUMBER() OVER(ORDER BY ItemLookupCode) AS RowID,

    MAX(ID) AS ID,
    ItemLookupCode,
    MAX(CAST(Notes AS varchar(max))) AS Notes,
    MAX(CONVERT(varchar(30), Price, 1)) AS Price,
    MAX(PictureName) AS PictureName
  FROM Item AS tbl
) AS i

WHERE RowID BETWEEN 1 AND 15;

上述查询返回以下错误:

  

Msg 8120,Level 16,State 1,Line 12   列' Item.ItemLookupCode'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

任何更熟悉SQL Server(2008 R2)的人都可以帮我填写空白吗?

1 个答案:

答案 0 :(得分:2)

您需要在分组结果上应用rownumber。

WITH cteresults AS 
(
    SELECT DISTINCT Max(i.id) AS ID, 
        i.itemlookupcode, 
        Max(Cast(i.notes AS VARCHAR(max))) AS Notes, 
        Max(CONVERT(VARCHAR(30), i.price, 1)) AS Price, 
        Max(i.picturename) AS PictureName 
    FROM   item AS i 
        LEFT JOIN nitroasl_pamtable AS n ON i.id = n.itemid 
    WHERE  ( i.id LIKE '%hdmi%' 
            OR i.itemlookupcode LIKE '%hdmi%' 
            OR i.notes LIKE '%hdmi%' 
            OR i.description LIKE '%hdmi%' 
            OR i.extendeddescription LIKE '%hdmi%' 
            OR n.manufacturerpartnumber LIKE '%hdmi%' 
            OR n.pam_keywords LIKE '%hdmi%' ) 
        AND (i.webitem = 0 AND i.price > 0) 
    GROUP  BY i.itemlookupcode
) 
,ctepagination AS 
(
    SELECT *, Row_number() OVER(ORDER BY itemlookupcode) AS RowID 
    FROM   cteresults
) 

SELECT * 
FROM   ctepagination 
WHERE  rowid BETWEEN 1 AND 15 

这应该没有CTE。但是,不确定它是否能解决您在评论中陈述的问题。

SELECT * FROM 
(
    SELECT *, Row_number() OVER(ORDER BY itemlookupcode) AS RowID from
    (
        SELECT DISTINCT Max(i.id) AS ID, 
            i.itemlookupcode, 
            Max(Cast(i.notes AS VARCHAR(max))) AS Notes, 
            Max(CONVERT(VARCHAR(30), i.price, 1)) AS Price, 
            Max(i.picturename) AS PictureName 
        FROM   item AS i 
            LEFT JOIN nitroasl_pamtable AS n ON i.id = n.itemid 
        WHERE  ( i.id LIKE '%hdmi%' 
                OR i.itemlookupcode LIKE '%hdmi%' 
                OR i.notes LIKE '%hdmi%' 
                OR i.description LIKE '%hdmi%' 
                OR i.extendeddescription LIKE '%hdmi%' 
                OR n.manufacturerpartnumber LIKE '%hdmi%' 
                OR n.pam_keywords LIKE '%hdmi%' ) 
            AND (i.webitem = 0 AND i.price > 0) 
        GROUP  BY i.itemlookupcode
    ) t1
) t2
WHERE  rowid BETWEEN 1 AND 15