2011-07-11 61 views
0

我对此问题有一个后续问题。SQL服务器根据字段中的值每天选择一条记录

SQL Server Get values of top three records and display in one row per person

ID Name  Date1     Value2 Date2     Value2 Date3     Value3 Date4     Value4 Date5     Value5 Date6     Value6 Date7     Value7 

12 John Smith 2011-06-27 14:06:10.517 None 2011-06-27 00:17:53.987 None 2011-06-26 21:56:07.577 Medium 2011-06-26 13:32:31.190 None 2011-06-26 02:47:54.357 None 2011-06-25 19:32:00.000 Medium 2011-06-25 13:43:22.000 Medium 
12 Jack Smith 2011-06-27 05:54:59.320 None 2011-06-26 06:28:55.033 None 2011-06-25 16:25:00.000 Medium 2011-06-25 14:27:11.017 Large 2011-06-25 06:11:45.793 Large 2011-06-24 19:33:24.520 Medium 2011-06-24 06:17:35.887 None 

我需要每天一个值。如果有一个不等于'无'的值,我需要该记录给定的日期。

这里的结果应该是什么样子:

ID Name  Date1     Value2 Date2     Value2 Date3     Value3 Date4     Value4 Date5     Value5 Date6     Value6 Date7     Value7 

12 John Smith 2011-06-27 00:17:53.987 None 2011-06-26 21:56:07.577 Medium 2011-06-25 13:43:22.000 Medium 
12 Jack Smith 2011-06-27 05:54:59.320 None 2011-06-26 06:28:55.033 None 2011-06-25 06:11:45.793 Large 2011-06-24 19:33:24.520 Medium 

我的原始数据的格式如下: (记录我需要标有*)

ID Name  Date     Value 
12 JACK Smith 2011-06-27 05:54:59.320 None * 
12 JACK Smith 2011-06-26 06:28:55.033 None * 
12 JACK Smith 2011-06-25 16:25:00.000 Medium 
12 JACK Smith 2011-06-25 14:27:11.017 Large 
12 JACK Smith 2011-06-25 06:11:45.793 Large * 
12 JACK Smith 2011-06-24 19:33:24.520 Medium * 
12 JACK Smith 2011-06-24 06:17:35.887 None 
12 JACK Smith 2011-06-23 00:30:28.363 None * 
12 JACK Smith 2011-06-22 00:47:41.800 None * 
12 JACK Smith 2011-06-21 06:03:55.000 None * 

任何帮助是极大的赞赏。

+0

试图理解你的问题......你可以(手动)将样本记录集放到一起,看看结果应该是什么样子,根据你迄今为止提供的内容。 – Chains

+0

这甚至可能吗? – Claudia

+0

是的 - 请参阅下面的我的(新)答案。这是一个非常简单的解决方案,但有很多代码来操纵日期。我添加了很多评论,以防它有帮助。 – Chains

回答

0

你问什么不清楚......

可以限制使用WHERE子句您的记录(这将完全删除的记录)......可能更容易做到这一点你的原始记录(在链接你贴)比上述修订后的记录...

WHERE value <> 'None' 

或者你可以保持的记录,只是限制了功能的显示(许多选项 - 这里有一个:)

Replace('None','') 

...这里的另一个问题:

CASE value WHEN 'None' THEN '' ELSE value END 
0

像这样的事情,然后...这将工作,但它可能有一个错字,因为我只是打字出来未经测试。

SELECT 
    ID, 
    Name, 
    Right(
    -- The Right() function will strip-off the leading integer that you need to first add to the date so 
    -- you can get the record you want. 
     Min(
     -- The Min() function will get a single record for you 
     -- the functions below will manipulate the date so that records with a non-'None' value are 
     -- guaranteed to have a larger date then records with a 'None' value. This is done by adding 
     -- an integer to the front of the date -- '0' for non-'None' values, and '1' for 'None' values. 
      Cast(CASE value WHEN 'None' THEN 1 ELSE 0 END as varchar(1)) 
      -- The CASE statement outputs a 0 or 1 
      -- The Cast() function changes the output to text instead of a number, so you can use the 
      -- string concat (+) later. 
      + 
      -- string concatenation, which only works on text, not numbers 
      Cast(Date as varchar(25)) 
      -- The Cast() function changes the date to text, so you can use it with the string concat above 
      ) 
     , 23 
     -- 23 should be the number of characters in the date itself 
     -- adjust the number up or down as necessary.    
     ) as myDate, 
    Value 
FROM 
    Table 
GROUP BY 
    ID, 
    Name, 
    Value 

这应该会减少您的原始记录集,以便它只包含您想要的记录。之后,您可以应用@Manfred Sorg为您的第一个问题提出的水平解决方案。

0

你想换位,我想。

你应该使用数据透视表的一些怎么说

表:支点 值:0,1,2,...

的想法能够将每个价值定位每一天在正确的列和之后,你需要做的查询组得到一个单列

select 

resultset.id, resultset.Name, 

case when not max(date1) is null then max(date1) 
else null end as date1, 
case when not max(value1) is null then max(value1) 
else '' end as value1, 
... 
... 
... 

from (

    select mltwngd.id, mltwngd.Name, 
     //sorry that part is ugly, ugly, 
     case when i=0 then datedd(day, mltwngdg.periodstart, auxtable.i) 
     else '' end as date1, 

     case when i=0 then datedd(day, mltwngdg.periodstart, auxtable.i) 
     else '' end as value1, 

     ... 
     ... 
     ... 

    from mylinealtable_with_nogooddesing mltwngd 

    inner join 
    (
     select id, min(date) periodstart, 
     max(date) as periodend, 
     datediff("dd", max(date), min(date)) as days 
     from mylinealtable_with_nogooddesing 
     where ... 
     group by id 
    ) as mltwngdg 
    on mltwngdg.id = mltwngd.id 

    inner join  
    (
     select * 
     from pivot 
     where i >= 0 and i < @period_max_days 
    )auxtable 
    on auxtable.i >0 and auxtable.i < days 
)resultset 

group by resultset.id, resultset.Name 

简化的想法是

declare @aux table (id int, [name] varchar(20), 
         date1 datetime, 
         valor1 varchar(10), 
         date2 datetime, 
         valor2 varchar(10) 
        ) 


insert into @aux(id, [name], date1, valor1, date2, valor2) 
values(1,'CARLOS','20110201','XP',NULL, '') 

insert into @aux(id, [name], date1, valor1, date2, valor2) 
values(1,'CARLOS',NULL, '','20110201','WIN7') 

select * from @aux 

select 
    x.id, x.name, 
    case when not max(date1) is null then max(date1) 
    else null end as date1, 
    case when not max(valor1) is null then max(valor1) 
    else null end as valor1, 
    case when not max(date2) is null then max(date2) 
    else null end as date2, 
    case when not max(valor1) is null then max(valor2) 
    else null end as valor2 
from @aux x 
group by x.id, x.name 
相关问题