从选择中选择最大值和第二个最大值,并将它们分组?

时间:2017-06-09 12:13:46

标签: sql sql-server database select

我一直在与这个问题作斗争一周,我需要帮助。

我有一个select语句,它会生成一个显示每个产品的表格,以及每个产品的导入日期。

如何创建一个显示以下内容的新表:

  • 产品在一栏中。
  • 另一栏中的最后日期。
  • 最后一栏中最后一个日期之前的日期。
  • 按产品分组。

我已经在网上搜索了一些信息,我无法让它发挥作用。大多数示例显示如何从表中查找仅一个倒数第二个值。 我希望按产品展示。

另外,由于使用了MSSQL,我无法使用LIMIT。

来自查询的表格

Result of query

查询

SELECT
    S.acIdent AS Product,
    CAST((SELECT top 1 adDate FROM the_move WHERE ackey = MI.acKey) AS date) AS ImportDate
FROM tHE_Stock S
    LEFT JOIN tHE_MoveItem MI
        ON S.acIdent = MI.acIdent
WHERE
    ( S.acWarehouse = '00051' ) AND
    (
        ( RIGHT(LEFT(MI.acKey,5),3) = '100' ) OR 
        ( RIGHT(LEFT(MI.acKey,5),3) = '190' )
    ) 
ORDER BY 
    S.acIdent, 
    CAST((SELECT top 1 adDate FROM the_move WHERE ackey = MI.acKey) AS date) 
        DESC         

4 个答案:

答案 0 :(得分:2)

您可以使用row_number和pivot进行查询,如下所示:

Select Product, [1] as [LastDate], [2] as [Last Before Last Date] from (
    Select top (2) with ties *, RowN=Row_Number() over(partition by Product order by ImportDate desc) from Products
        Order by (Row_Number() over(partition by Product order by ImportDate desc) -1)/2+1
) a
pivot (max(ImportDate) for RowN in([1],[2])) p

使用此查询输出您的类似输入,如下所示:

+---------+------------+-----------------------+
| Product |  LastDate  | Last Before Last Date |
+---------+------------+-----------------------+
|  075031 | 2014-07-08 | 2014-06-19            |
|  075032 | 2014-12-09 | NULL                  |
|  075034 | 2016-03-10 | 2014-07-08            |
|  075036 | 2016-03-08 | 2015-09-08            |
+---------+------------+-----------------------+

答案 1 :(得分:1)

所以,如果我理解正确,你需要acIdent,然后是最新的导入日期,然后是第二个到最新的导入日期。

困难的是第二次到最新的进口日期。为此,您需要排除最新的导入日期。

这可能有效:

SELECT S.acIdent AS Product,
    (SELECT MAX(adDate) 
     FROM tHE_MoveItem MI2
     WHERE MI2.s.acIdent = MI.acIdent) AS LastImportDate,

    (SELECT MAX(adDate) 
     FROM tHE_MoveItem MI2
     WHERE MI2.acIdent = MI.acIdent
        AND MI2.ImportDate != (SELECT MAX(ImportDate) 
                                FROM tHE_MoveItem MI3
                                WHERE MI2.s.acIdent = MI3.acIdent)) 
            AS PreviousImportDate,
FROM tHE_Stock S
    INNER JOIN tHE_MoveItem MI
        ON s.acIdnet = MI.acIdent

答案 2 :(得分:1)

您可以使用rownumber而不是max来查找last和secondlast日期。

Declare @mytable table (productnr varchar(10), importdate date)
insert into @mytable values
('075031', '2014-07-08'),
('075031', '2014-07-07'),
('075031', '2014-07-06'),

('075032', '2014-07-10'),
('075032', '2014-07-09'),
('075032', '2014-07-06')

;with products_cte as
(select productnr,importdate, ROW_NUMBER() over (partition by productnr order by importdate desc) rn
from @mytable
)

select t1.productnr, t1.importdate lastDate,t2.importdate SecondLastDate
from products_cte t1
left join products_cte t2 on t1.productnr = t2.productnr and t2.rn = 2
where t1.rn = 1

答案 3 :(得分:1)

One more option with lead and lag.

select productnr,importdate as lastdate,prev as secondlastdate
from (select productnr,importdate
      ,lead(importdate) over(partition by productnr order by importdate) as nxt
      ,lag(importdate) over(partition by productnr order by importdate) as prev
      from tbl
     ) t
where nxt is null   

lead on the date for last row (ordered by importdate per productnr) would be null and lag gives you the previous date before the lastdate.