好的,我有这两张桌子 -
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
因此,当我试图在2009年12月10日到2009年10月30日之间的两个日期之间建立一个列表。它应该显示一个像 -
这样的列表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表可以有一天的多个条目。任何人都可以帮助我...
答案 0 :(得分: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);
答案 1 :(得分: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]
答案 2 :(得分:0)
您应该从DimDate
表和JOIN
BioUser
开始:
SELECT u.Weight, u.DateAdded
FROM DimDate d
LEFT OUTER JOIN d.Date = u.DateAdded
然后,对NULL
表中未填充的任何日期显示BioUser
。
答案 3 :(得分:0)
Select Weight, Date
from Dimdate d left outer join BioUser b
on b.DateAdded= d.Date
如果那天没有重量值,应该返回重量的空值。
HTH
你需要从dimDate表中提取日期,而不是bioUser,这可能是null
答案 4 :(得分: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)