SQL Server根据字段中的值每天选择一条记录

时间:2011-07-11 23:39:19

标签: sql-server

我对这个问题有一个后续问题。

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

我需要每天获得一个值。如果有一个不等于'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    *

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

不清楚你在问什么...

您可以使用WHERE子句限制记录集(这将完全删除记录)...可能更容易在原始记录集(在您发布的链接上)上执行此操作,而不是在上面的此修订记录集上执行此操作...

WHERE value <> 'None'

或者您可以保留记录,并使用一个功能限制显示(许多选项 - 这里是一个:)

Replace('None','')

......这是另一个:

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

答案 1 :(得分: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提出的横向解决方案。

答案 2 :(得分:0)

你想做换位,我想。

你应该使用数据透视表一些

table:pivot 值: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