SQL max by 2列,或第一个和最后一个聚合函数

时间:2015-06-04 11:03:11

标签: sql sql-server

如何在sql中通过colum1 1然后通过colum 2获得max?并且是第一个还是最后一个聚合函数?

我试过两种方法:

1 - 它是我的最大日期,但最高价格与最大日期无关:

SELECT doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId,MAX(price_list_t._Date), MAX (price_list_t.Price)
FROM [AcKits] kits_t
INNER JOIN [DocAcKits] doc_kits_t
ON  kits_t.DocId = doc_kits_t.Id
LEFT OUTER JOIN [PriceList] price_list_t
ON price_list_t._Date <= doc_kits_t.DateOper
 AND kits_t.GoodId = price_list_t.AcGoodsId
 GROUP BY kits_t.DocId,kits_t.GoodId,doc_kits_t.DateOper

2-我没有找到第一个聚合函数:

SELECT doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId, /*top or first*/(price_list_t._Date),/*top or first*/ (price_list_t.Price)
FROM [AcKits] kits_t
INNER JOIN [DocAcKits] doc_kits_t
ON  kits_t.DocId = doc_kits_t.Id
LEFT OUTER JOIN [PriceList] price_list_t
ON price_list_t._Date <= doc_kits_t.DateOper
 AND kits_t.GoodId = price_list_t.AcGoodsId
 GROUP BY kits_t.DocId,kits_t.GoodId,doc_kits_t.DateOper
 ORDER BY price_list_t._Date, price_list_t.Price

完整的解释:

我有3张桌子:

Table 1:
    PriceList (Id, AcProviderId, AcGoodsId, Price, _Date)
Table 2:
    DocAcKits (Id, Number, DateOper)
Table 3:
    AcKits (Id, DocId, GoodId, Count) 

在结果我应该得到表: AS

(DateOpr , DocId, Number, TotalPrice )

TotalPrice是具有相同DocId的商品的价格总和 其中,GoodList中的GoodId与PriceList中的GoodId链接它必须满足条件(DocAcKits.DateOper <= PriceList._Date且日期是最大值,如果有超过一个最大日期,我们将获得最高价格)

感谢您的帮助,最终的解决方案是:

;WITH CTE AS 
(
  SELECT ROW_NUMBER()OVER(PARTITION BY kits_t.GoodId,doc_kits_t.DateOper ORDER BY price_list_t._Date DESC, price_list_t.Price DESC) rn,
  doc_kits_t.DateOper as DateOper, kits_t.DocId as DocId,
   ISNULL (price_list_t.Price,0) as Price,
  kits_t.Count as Count,
  doc_kits_t.Number as Number
  FROM [AcKits] kits_t
  INNER JOIN [DocAcKits] doc_kits_t
  ON  kits_t.DocId = doc_kits_t.Id
  LEFT OUTER JOIN [PriceList] price_list_t
  ON price_list_t._Date <= doc_kits_t.DateOper
   AND kits_t.GoodId = price_list_t.AcGoodsId
   WHERE doc_kits_t.DateOper BETWEEN @StartDate AND @EndDate
  )
  INSERT @ret
  SELECT DateOper, Number, SUM(Price * Count)as TotalPrice  FROM CTE t1
  WHERE rn = 1
  GROUP BY DocId,DateOper,Number

4 个答案:

答案 0 :(得分:1)

如果您想获得max(price)的所有记录,请执行以下操作:

 SELECT doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId,price_list_t._Date, price_list_t.Price
    FROM [AcKits] kits_t
    INNER JOIN [DocAcKits] doc_kits_t
    ON  kits_t.DocId = doc_kits_t.Id
    LEFT OUTER JOIN [PriceList] price_list_t
    ON price_list_t._Date <= doc_kits_t.DateOper
    AND kits_t.GoodId = price_list_t.AcGoodsId
    WHERE price_list_t.price = (
                                SELECT Max(price) 
                                FROM price_list_t)
    GROUP BY kits_t.DocId,kits_t.GoodId,doc_kits_t.DateOper

或者如果你想获得最大日期:

SELECT doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId,price_list_t._Date, price_list_t.Price
        FROM [AcKits] kits_t
        INNER JOIN [DocAcKits] doc_kits_t
        ON  kits_t.DocId = doc_kits_t.Id
        LEFT OUTER JOIN [PriceList] price_list_t
        ON price_list_t._Date <= doc_kits_t.DateOper
        AND kits_t.GoodId = price_list_t.AcGoodsId
        WHERE price_list_t.date= (
                                    SELECT Max(date) 
                                    FROM price_list_t)
        GROUP BY kits_t.DocId,kits_t.GoodId,doc_kits_t.DateOper

答案 1 :(得分:0)

通常,您会使用row_number()执行此操作。我发现你的解释和查询有点难以理解,但我认为你想要这个:

SELECT t.*
FROM (SELECT doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId,
             ROW_NUMBER() OVER (PARTITION BY kits_t.DocId, kits_t.GoodId, doc_kits_t.DateOper
                                ORDER BY price_list_t._Date) as seqnum
      FROM [AcKits] kits_t INNER JOIN
           [DocAcKits] doc_kits_t
           ON kits_t.DocId = doc_kits_t.Id LEFT OUTER JOIN
           [PriceList] price_list_t
           ON price_list_t._Date <= doc_kits_t.DateOper AND
              kits_t.GoodId = price_list_t.AcGoodsId
     ) t
WHERE seqnum = 1

答案 2 :(得分:0)

您可以ROW_NUMBER()使用PARTITION BY来实现此目标

;WITH CTE AS 
(
SELECT ROW_NUMBER()OVER(PARTITION BY kits_t.DocId,kits_t.GoodId,doc_kits_t.DateOper ORDER BY price_list_t._Date DESC) rn,
doc_kits_t.DateOper, kits_t.DocId, kits_t.GoodId
FROM [AcKits] kits_t
INNER JOIN [DocAcKits] doc_kits_t
ON  kits_t.DocId = doc_kits_t.Id
LEFT OUTER JOIN [PriceList] price_list_t
ON price_list_t._Date <= doc_kits_t.DateOper
 AND kits_t.GoodId = price_list_t.AcGoodsId
)
SELECT * FROM CTE
WHERE rn = 1

注意:

如果MAX使用price_list_t._Date

,则需要ORDER BY price_list_t._Date DESC条记录

如果MIN使用price_list_t._Date

,则需要ORDER BY price_list_t._Date ASC条记录

答案 3 :(得分:0)

要将MAX或MIN转换为ROW_NUMBER,您只需将列从GROUP BY移动到PARTITION BY和ORDER BY,使得您想要的行是第一行:

SELECT *
FROM 
 (
   SELECT *,
      ROW_NUMBER() 
      OVER (PARTITION BY doc_kits_t.DateOper, kits_t.DocId,kits_t.GoodId 
            ORDER BY price_list_t._Date DESC, price_list_t.Price DESC) AS rn
   FROM [AcKits] kits_t
   INNER JOIN [DocAcKits] doc_kits_t
     ON  kits_t.DocId = doc_kits_t.Id
   LEFT OUTER JOIN [PriceList] price_list_t
     ON price_list_t._Date <= doc_kits_t.DateOper
    AND kits_t.GoodId = price_list_t.AcGoodsId
 ) AS dt
WHERE rn = 1: