SQL Server根据最短日期和另外两列选择多行

时间:2018-06-27 15:24:52

标签: sql sql-server

更新: 这是我的实际查询:如果我在内部select(注释掉的where子句)中设置了一个员工ID,则此查询将非常有效。但是,如果我拿出该雇员ID尝试为所有雇员运行该ID,它将(几乎)选择该雇员的所有日期。

SELECT* FROM ( 
    SELECT id, shop_id, local_id, employee_id, invoice_date, 
    LAG(shop_id)OVER(ORDER BY invoice_date) as new_Col1, 
    LAG(local_id)OVER(ORDER BY invoice_date) as new_Col2 
    FROM tmpMemPayment 
) as A 
WHERE NOT( (shop_id = ISNULL(new_Col1,'')) 
           and (local_id = ISNULL(new_Col2,'')) )

----结束更新

我正在尝试一个复杂的查询,它可以接近但不够接近。我尝试过分区,但仍然没有喜悦。

我正在尝试:

MyTable:     Col1 Col2日期

x        y      1/1/2018
x        y      1/1/2017
x        z      1/1/2016
x        y      1/1/2015
a        b      1/1/2014
a        b      1/1/2013
x        y      1/1/2012

我需要每个分区中具有最少日期的每一行,其中对于连续日期集,由col1和col2定义的分区是相同的 即我需要的结果集是:

x    y    1/1/2017
x    z    1/1/2016
x    y    1/1/2015
a    b    1/1/2013
x    y    1/1/2012

我最近得到的是:

select t1.col1, t1.col2, min(t1.date)
from
MyTable t1
and t1.Date < 
(
select max(t2.Date) from MyTable t2 where 
(t2.col1 !=t1.col1 or t2.col2 != t1.col2)
)
group by col1, col2

union 


select t1.col1, t1.col2, min(t1.date)
from
MyTable t1
and t1.Date > 
(
select min(t2.Date) from MyTable t2 
where (t2.col1 !=t1.col1 or t2.col2 != t1.col2)
)
group by col1, col2

3 个答案:

答案 0 :(得分:0)

您可以使用LEAD()函数将当前行的值与下一行的值进行比较:

;with cte as (select 
                    *
                  , LEAD(Col1, 1) over (ORDER BY DT desc) as Col1_Next 
                  , LEAD(Col2, 1) over (ORDER BY DT desc) as Col2_Next 
              from MyTable)

select Col1, Col2, DT from cte
where Col1 <> ISNULL(Col1_Next, '') OR Col2 <> ISNULL(Col2_Next, '')

此处的工作示例:SQLFiddle

有关LEAD()功能的更多信息

答案 1 :(得分:0)

尝试一下:

WITH CTE
AS
(
SELECT 'x' as Col1, 'y' as Col2, '1/1/2018' as Date
UNION ALL
SELECT 'x' as Col1, 'y' as Col2, '1/1/2017' as Date
UNION ALL
SELECT 'x' as Col1, 'z' as Col2, '1/1/2016' as Date
UNION ALL
SELECT 'x' as Col1, 'y' as Col2, '1/1/2015' as Date
UNION ALL
SELECT 'a' as Col1, 'b' as Col2, '1/1/2014' as Date
UNION ALL
SELECT 'a' as Col1, 'b' as Col2, '1/1/2013' as Date
UNION ALL
SELECT 'x' as Col1, 'y' as Col2, '1/1/2012' as Date

)
--Actual query  
SELECT col1,col2,Date FROM 
(
   SELECT col1, col2, [Date], LAG(Col1)OVER(ORDER BY [DATE]) as new_Col1, LAG(Col2)OVER(ORDER BY [DATE]) as new_Col2
   FROM CTE
) as A
WHERE NOT(
          (col1 = ISNULL(new_Col1,'')) and (col2 = ISNULL(new_Col2,''))
         )

答案 2 :(得分:0)

我只会使用lag()。这是一种方法:

select col1, col2, date
from (select t.*,
             lag(date) over (order by date) as prev_date,
             lag(date) over (partition by col1, col2 order by date) as prev_date_2
      from t
     ) t
where prev_date is null or prev_date <> prev_date_2;

与在列上使用lag()相比,此方法的优势在于它可以轻松扩展到任意数量的列-它们只是进入partition by子句,而不是生成附加列以及where子句中的其他条件。