2017-08-16 26 views
9

Mam tabelę, a jednym z pól jest pole daty.wybieranie dat z tabeli na dwie kolumny

Zostałem poproszony o napisanie zapytania, które zwraca listę odrębnych dat (uporządkowanych) w kolumnie A, a następnie mają inną kolumnę, np. B dat, gdzie data w kolumnie B jest największą datą, która jest mniejsza niż kolumna A.

MyDateField 

    2017-01-01 
    2017-01-01 
    2017-01-01 
    2017-01-02 
    2017-01-02 
    2017-01-03 
    2017-01-04 
    2017-01-05 
    2017-01-05 
    2017-01-05 

Odpowiedź wymagane

2017-01-05  2017-01-04 
    2017-01-04  2017-01-03 
    2017-01-03  2017-01-02 
    2017-01-02  2017-01-01 
    2017-01-01  
+0

czyni tę kolumnę B pochodzić również z he samym stole, lub po prostu "date_column -" 1 day' "to zrobi? –

+0

pochodzi z tej samej tabeli – mHelpMe

Odpowiedz

7

Jeśli używasz SQL-Server 2012+, a następnie można użyć LAG() pobrać ostatnią największą datę z tabeli:

SELECT t.date, 
     LAG(t.date,1) OVER(ORDER BY t.date) as last_biggest_date 
FROM (SELECT DISTINCT s.dateField FROM YourTable s) t 
+1

Zauważając, że jest to SQL Server 2012+, chociaż nie opublikował swojego DBMS. – justiceorjustus

+0

@justiceorjustus Masz rację, edytuj. – sagi

+1

który jest genialny! – mHelpMe

1

Można użyć zastosować podzapytanie wrócić mniejszy datę w drugiej kolumnie:

select distinct t1.MyDateField, x.MyDateField 
from MyTable t1 
outer apply (select max(MyDateField) MyDateField 
      from MyTable t2 
      where t1.MyDateField> t2.MyDateField) x 
+0

Tylko jedna główka w górę ... "TOP 1" nie ma gwarancji, że będzie tą, której chcesz (lub nawet taką samą za każdym razem), bez określania "ZAMÓWIENIA" w tym samym pod-zapytaniu. – scsimon

+0

Masz rację, przełączam 'TOP 1' na' MAX() 'aby zawsze zwracał poprawną datę – Mat

2

Można to zrobić z CTE między innymi. Otrzymuje listę różnych dat, a następnie korzysta z samołączenia.

with cte as(
    select distinct 
     MyDateField 
    from 
     YourTable) 

select 
    c.MyDateField 
    ,max(c2.MyDateField) as MaxDate 
from 
    cte c 
left join cte c2 on c2.MyDateField < c.MyDateField 
group by 
    c.MyDateField 
order by 
    c.MyDateField 

Albo prosty samosprzężenie bez CTE

--in this case DISTINCT isn't really needed, but left in case there are other columns 
select distinct 
    c.MyDateField 
    ,max(c2.MyDateField) as MaxDate 
from 
    myTable c 
left join myTable c2 on c2.MyDateField < c.MyDateField 
group by 
    c.MyDateField 
order by 
    c.MyDateField 
+0

Nie znam składni M $ -SQL CTE, ale powinno to zadziałać, nawet bez CTE ... –

+0

Jesteś poprawne @UsagiMiyamoto, po prostu łatwiej jest czytać dla wielu ludzi. – scsimon

0
SELECT d, LAG(d) OVER (ORDER BY d) AS d2 
    FROM (
      SELECT DISTINCT d 
       FROM (VALUES ('2017-01-01'), 
          ('2017-01-01'), 
          ('2017-01-01'), 
          ('2017-01-02'), 
          ('2017-01-02'), 
          ('2017-01-03'), 
          ('2017-01-04'), 
          ('2017-01-05'), 
          ('2017-01-05'), 
          ('2017-01-05')) AS dates(d) 
     ) AS d(d) 
ORDER BY d DESC; 

wyjściowa:

d   d2 
---------- ---------- 
2017-01-05 2017-01-04 
2017-01-04 2017-01-03 
2017-01-03 2017-01-02 
2017-01-02 2017-01-01 
2017-01-01 NULL 
0
with CTE as(
select 
ROW_NUMBER() over (order by MyDateField) 'RN', 
MyDateField from TempTable 
group by MyDateField) 
select t2.MyDateField,t1.MyDateField from CTE t1 
right join CTE t2 
on t1.RN=t2.RN-1 
order by t2.MyDateField desc 
Powiązane problemy