2016-08-16 60 views
-4

我有一个表,看起来像这样:选择行

id person_id element_name element_value element_effective_date 
1 123   a     25    07/01/16 
2 123   b    100    05/01/16 
3 123   a     25    07/20/16 
4 456   b    101    01/01/16 
5 456   b    102    04/01/16 
6 456   a     25    08/01/16 
7 789   b    101    08/01/16 
8 789   c    200    07/25/16 
9 789   d    201    07/26/16 

我想从表中选择的person_ids了selected element_name,其中element_value等于某个值,行的生效日期等于给定日期,或者是person_id的第一行,生效日期小于给定日期。

例如,如果element_name = a且element_value = 25且给定日期为8/5/2016,则所选行将为6和3.如果给定日期更改为7/25/2016,则选定的行会是3.如果日期更改为2016年7月15日,然后选定行是1

+2

如果你存储在您的入住日期您的生活会更容易在ISO格式,而不是(疯狂)美国格式。如果日期列的数据类型是“日期”而不是“文本”,那么你的生活会更容易*。我建议首先解决其中的一个问题,然后你就不必问这个问题。 – Bohemian

+0

标记使用的dbms。 (许多产品都有自己的非ANSI功能,用于日期/时间。) – jarlh

+0

还可添加预期结果。 – jarlh

回答

1
​​
+0

感谢您的解决方案。我认为它不起作用。使用第一个示例,结果将是第1,3和6行。第1行和第3行与person_id = 123相关联。我只想返回第3行和第6行 - 每个person_id只有一行最大值。 –

+0

你的rdbms是什么? –

-1

数据存储为YYYYMMDD,然后用这个语句:

SELECT * 
FROM table_name 
WHERE element_value = @value 
AND element_name = @name 
AND element_effective_date <= @date 
0

你的问题并不清楚,无论如何,如果我正确地理解你的问题,下面是解决方案

declare @element_name varchar(1)= 'a' 
declare @element_value int = 25 
declare @element_effective_date smalldatetime ='7/15/2016' 
--'7/25/2016' 
--'8/5/2016' 

create table #a(
id int, 
person_id int, 
element_name varchar(1), 
element_value int, 
element_effective_date smalldatetime) 

insert into #a 
select 1, 123, 'a', 25,'07/01/2016' union 
select 2, 123, 'b', 100,'05/01/2016' union 
select 3, 123, 'a', 25,'07/20/2016' union 
select 4, 456, 'b', 101,'01/01/2016' union 
select 5, 456, 'b', 102,'04/01/2016' union 
select 6, 456, 'a', 25,'08/01/2016' union 
select 7, 789, 'b', 101,'08/01/2016' union 
select 8, 789, 'c', 200,'07/25/2016' union 
select 9, 789, 'd', 201,'07/26/2016' 



select * 
Into #solutionDataset 
from #a 
where [email protected]_name 
and [email protected]_value 
and element_effective_date < @element_effective_date 

/* 
I want to select the person_ids from the table for a selected element_name where the element_value is equal to some value and the rows' effective date is equal to a given date or is the first row for the person_id with the effective date less than the given date. 
*/ 
if(@@ROWCOUNT=1) 
begin 
select * from #solutionDataset 
end 

else 
begin 
    select * from #solutionDataset 
    where id not in(select min(id) from #a where [email protected]_name and [email protected]_value) 
end 
-1

这工作:

select person_id 
from 
(
    select max(element_effective_date), person_id 
    from 
    (
     select t.person_id, t.element_effective_date 
     from table t 
     where t.element_name = 'a' and t.element_value = 25 
      and t.element_effective_date <= '2016-08-05' 
    ) as foo 
    group by person_id 
); 

THX您的意见。

+0

如果您想要的只是personid,那么该查询不必要的复杂。 – shawnt00

+0

其实我不是downvoter。这里是一个简单的查询'从 t中选择不同的t.person_id,其中t.element_name ='a'且t.element_value = 25且t.element_effective_date <='2016-08-05'' – shawnt00

0

不确定我是否遵循了所有你想要的逻辑,但是这些应该是非常接近的。我也假设SQL Server,但这只应该参数名称。

如果你能保证id值都在增加:

select * 
from <T> 
where id in (
    select max(id) 
    from <T> 
    where element_value = @element_value and element_effective_date <= @effective_date 
    group by person_id 
) 

如果没有,但你仍然可以保证effective_date无关系:

select t.* 
from 
    <T> t 
    inner join 
    (
     select person_id, element_value, max(element_effective_date) as max_date 
     from <T> 
     where element_effective_date <= @effective_date 
     group by person_id 
    ) as m 
     on  m.person_id = t.person_id 
      and m.element_value = t.element_value 
      and m.max_date = t.element_effective_date 
where 
    t.element_value = @element_value