2014-02-21 4 views
1

Первоначально я думал, что это будет довольно просто, но по какой-то причине я борюсь с ним.SQL Лучший способ присоединиться к день за днем ​​данных в одну строку, включая новые и удаленные идентификаторы

Если у меня есть таблица, которая выглядит следующим образом:

table1 
Date  ID  Quantity 
2/21  1  100 
2/21  2  500 
2/21  3  200 
2/20  2  600 
2/20  3  400 
2/20  5  2000 

И я хочу присоединиться к этой информации, чтобы выглядеть следующим образом:

ID  prev_date  prev_quantity curr_date  curr_quantity 
1   2/20   0    2/21   100 
2   2/20   600    2/21   500 
3   2/20   400    2/21   200 
5   2/20   2000    2/21   0 

Хитрости быть ID-не имеет запись за предыдущий день (так что сделайте 0), а идентификатор 5 не имеет записи для текущего дня (также сделайте это 0)

Каков наилучший способ сделать это? Заранее спасибо!!

+0

Я ценю всякую помощь на этом, но я не уверен, если я объясняю это неправильно , Ни одно из этих решений не работает, только один удаленно закрыт - один из @sureshhh - но даже это не содержит строк/идентификаторов, которые существуют для минимальной даты, а не максимальной даты. ** Я просто хочу создать 1 строку для каждого уникального идентификатора, который существует в любой день. ** Может быть, я перепутал вопрос? Еще раз спасибо за любые отзывы об этом – Jay

ответ

1

Это может помочь U ,,,,,

SELECT 
    ISNULL(T.ID,T1.ID), 
    ISNULL(T.DATE,GETDATE()) AS 'CurrDate', 
    ISNULL(T.Quantity,0) AS 'CurrQty', 
    ISNULL(T1.DATE,GETDATE()-1) AS 'PrevDate' , 
    ISNULL(T1.Quantity,0) AS 'PrevQty' 
FROM 
    ( 
     SELECT 
       T.ID, 
       T.Quantity, 
       T.DATE 
     FROM @TABLE T 
     WHERE T.DATE = CONVERT(VARCHAR,GETDATE(),100) 
    )T 
    FULL OUTER JOIN 
    (
     SELECT 
      T1.ID, 
      T1.Quantity, 
      MAX(T1.DATE) AS [DATE] 
     FROM @TABLE T1 
     WHERE T1.DATE <> CONVERT(VARCHAR,GETDATE(),100) 
     GROUP BY T1.ID,T1.Quantity 
    ) T1 ON T.ID = T1.ID 
+0

Спасибо, это сработало !! – Jay

1
SELECT curr.ID, ISNULL(Prev.date, DATEADD(DD, -1, curr.Date)) AS Prev_Date,   
     ISNULL(prev.Quantity, 0) AS Prev_Quantity, 
     ISNULL(curr.date, DATEADD(DD, 1, prev.Date)) AS Curr_Date, ISNULL(curr.Quantity, 0) AS Curr_Quantity 
FROM table1 curr 
      FULL OUTER JOIN 
     table1 prev 
     ON curr.ID = prev.ID AND prev.Date = DATEADD(DD, -1, curr.Date) 
+1

Вы тоже меня избили, мои взгляды более или менее идентичны вашим, за исключением того, что у меня был ID внутри Isnull, так как вы иногда получаете NULL для 'curr.ID'. Поскольку они должны равняться друг другу в JOIN или быть NULL, кажется безопасным делать Isnull (curr.ID, prev.ID) '. –

+0

Спасибо, я попробую это, но что, если день за днем ​​не всегда разница на 1 день, могут быть пробелы, например, в выходные, праздники? У меня должны быть параметры для @ CURRDATE и @ PREVDATE, поэтому я могу, возможно, просто подключить их вместо dateadds? Еще раз спасибо – Jay

+0

Не использовать DateAdd будет означать, что вам нужно указать, какие даты присоединиться (что позволит вам сделать только 1 установить время), или вам понадобится отдельная таблица, в которой установлены отношения date-> previous date. Подобную таблицу можно также создать с использованием существующих данных с помощью запроса. Это зависит от того, как выглядят ваши данные. IE, если у вас есть список сотен дней с пробелами здесь и там, лучшим вариантом будет создание второго запроса на сопоставление даты. – Wabi

0

Вы можете решить проблему с пробелами, используя разряд. Кроме того, вместо ISNULL использовать UNION:

SELECT RANK() OVER (ORDER BY ID,DATE) rank, ID, date, quantity 
INTO temp1 
FROM (
SELECT date, ID, quantity 
      FROM table1 
     UNION ALL 
     SELECT dateadd(day,-1,MIN(date)) date, ID, 0 quantity 
      FROM table1 
      GROUP BY ID 
     UNION ALL 
     SELECT dateadd(day,1,MAX(date)) date, ID, 0 quantity 
      FROM table1 
      GROUP BY ID 
) AS U; 

SELECT p.ID, p.date prev_date, p.quantity prev_quantity, 
      c.date curr_date, c.quantity curr_quantity 
FROM temp1 p INNER JOIN temp1 c ON c.rank = p.rank + 1 AND c.ID = p.ID