2010-08-20 59 views
0

好了,我有這兩個表 -用於在兩個日期之間添加字段缺失值的SQL查詢?

BioUser- UserId,Weight,DateAdded 
DimDate-Date // It has basically all the dates for any period..its basically a table with all dates till 2050 

現在BioUser表有條目重量的用戶而不是每天,但每當他們進入自己的體重。所以我想基本上爲BioUser中的所有這些缺失日期建立日期和權重的值列表。爲了更好地在這裏解釋一下是一個例子 -

BioUser -

UserId Weight DateAdded 
1  178 10/12/2009 
1  175 10/18/2009 
1  172 10/27/2009 

所以,當我想建立兩個日期之間的名單說10/12/2009至10/30/2009。它應該顯示一個類似的列表 -

Weight Date 

178 10/12/2009 
178 10/13/2009 
178 10/14/2009 
178 10/15/2009 
178 10/16/2009 
178 10/17/2009 
175 10/18/2009 
175 10/19/2009 
175 10/20/2009 
175 10/21/2009 
175 10/22/2009 
175 10/23/2009 
175 10/24/2009 
175 10/25/2009 
175 10/26/2009 
172 10/27/2009 
172 10/28/2009 
172 10/29/2009 
172 10/30/2009 

我有查詢是這樣的 -

Select Weight,DateAdded from BioUser join Dimdate on BioUser.DateAdded=Dimdate.Date 

但上面並沒有以某種方式工作,我想獲得的重量從BioUser和最新的條目只有一個條目也作爲BioUser表可以有多個條目的day.Can任何人,請幫助我..

回答

0

感謝大家對他們的答案,這是我做到了 -

SELECT  
     (SELECT TOP (1) Weight 
     FROM BioUser AS b 
     WHERE (CAST(DateTested AS Date) <= k.Date) AND (UserId= @UserId) 
     ORDER BY DateTested DESC) AS Weight, Date AS DateTested 
FROM  DimDate AS k 
WHERE  (Date BETWEEN @StartDate AND @EndDate) 
0

你應該與DimDate表開始,JOINBioUser上:

SELECT u.Weight, u.DateAdded 
FROM DimDate d 
    LEFT OUTER JOIN d.Date = u.DateAdded 

然後,如果在BioUser表中沒有填寫任何日期,則會顯示NULL

0
Select Weight, Date 
from Dimdate d left outer join BioUser b 
on b.DateAdded= d.Date 

如果當天沒有體重值,應該返回空位以表示體重。

HTH

你需要從dimDate表,而不是bioUser,它可以爲null

2

我只包括參數拉日在這裏說明,你需要指定的最早日期最晚日期。如有必要,這兩個值可以從您的數據中推導出來。

這裏的訣竅是將您的源數據轉換爲具有開始日期和結束日期的範圍。然後,我們生成一個涵蓋所需時間段的連續日期日曆表,並加入我們的範圍以確定結果。

Declare @MinDate datetime; 
Declare @MaxDate datetime; 

Set @MinDate = '2009-10-12'; 
Set @MaxDate = '2009-10-30'; 

With BioUser As 
    (
    Select 1 As UserId, 178 As Weight, '2009-10-12' As DateAdded 
    Union All Select 1, 175, '2009-10-18' 
    Union All Select 1, 172, '2009-10-27' 
    ) 
    , Calendar As 
    (
    Select @MinDate As [Date] 
    Union All 
    Select DateAdd(d,1,[Date]) 
    From Calendar 
    Where [Date] < @MaxDate 
    ) 
    , BioUserDateRanges As 
    (
    Select B1.UserId, B1.Weight, B1.DateAdded As StartDate, Coalesce(Min(B2.DateAdded),@MaxDate) As EndDate 
    From BioUser As B1 
     Left Join BioUser As B2 
      On B2.UserId = B1.UserId 
       And B2.DateAdded > B1.DateAdded 
    Group By B1.UserId, B1.Weight, B1.DateAdded 
    ) 
Select BR.Weight, C.[Date] 
From Calendar As C 
    Join BioUserDateRanges As BR 
     On BR.StartDate <= C.[Date] 
      And BR.EndDate >= C.[Date] 
Option (MaxRecursion 0); 
+0

這是一個聰明的方式來構建的日曆。我沒有意識到你可以像那樣遞歸地做 – 2010-08-20 21:31:33

1
WITH Dimdate As 
(
SELECT DATEADD(DAY,-number,CAST('2009-12-31' AS DATETIME)) AS [Date] 
from master.dbo.spt_values where type='p' 
), 
BioUser AS 
(SELECT 1 AS [UserId], 178 AS [Weight], CAST('20091012' AS DATETIME) AS DateAdded 
UNION ALL 
SELECT 1 AS [UserId], 175 AS [Weight], CAST('20091018' AS DATETIME) 
UNION ALL 
SELECT 1 AS [UserId], 172 AS [Weight], CAST('20091027' AS DATETIME) 
), 
NumberedT AS 
(
SELECT [UserId],[Weight],DateAdded, 
     ROW_NUMBER() OVER (PARTITION BY [UserId] ORDER BY DateAdded) AS RN 
FROM BioUser 
) 
SELECT 
    ISNULL(T1.[UserId], T2.[UserId]) [UserId], 
    ISNULL(T1.Weight, T2.Weight) [Weight], 
    Dimdate.[Date] 
FROM NumberedT T1 
FULL OUTER JOIN NumberedT T2 ON T2.RN = T1.RN+1 AND T2.[UserId]= T1.[UserId] 
INNER JOIN Dimdate ON 
    (Dimdate.[Date] >= ISNULL(T1.DateAdded, T2.DateAdded) 
     AND Dimdate.[Date]< T2.DateAdded) 
OR 
    (T2.DateAdded IS NULL AND Dimdate.[Date]=T1.DateAdded) 
ORDER BY Dimdate.[Date] 
相關問題