如何在输入日期SQL上选择最后一个条目

时间:2018-03-30 19:02:25

标签: sql oracle

我有一组数据,我将日期的用户输入传递给表格。

我要做的是设置逻辑:

这是原始表格:

User    DATE_TIME        Value
HH1     5/20/2018 1:00    50
HH1     5/20/2018 10:00   50
HH1     5/20/2018 18:00   120
HH1     5/25/2018 12:00   10
HH1     5/26/2018 10:00   15

用户将05/20/2018传递给DATE_TIME

的sql查询

输出如下:

User    DATE_TIME        Value
HH1     5/20/2018 1:00    50
HH1     5/20/2018 10:00   50
HH1     5/20/2018 18:00   120

现在用户将05/21/2018传递到DATE_TIME

Result is nothing

我想要完成的是......如果当天没有结果,那么在数据库中提取最新值,在这种情况下:

User    DATE_TIME        Value
HH1     5/20/2018 18:00   120

我不确定如何找到这个最近的价值。

任何帮助将不胜感激,谢谢!

4 个答案:

答案 0 :(得分:2)

在我的下面的解决方案中,我将基表TBL命名为“USR”,因为"用户"是一个Oracle关键字。

大多数工作都是在子查询中完成的。首先查看FROM子句:我交叉连接到一个小子查询,该子查询根据输入创建一个实际日期(假设以MM/DD/YYYY格式的字符串形式给出)。根据您的应用程序,您可以直接输入日期,而不必在查询中转换为日期。无论如何,您应该能够使用输入日期。

WHERE子句将行限制为截至给定输入日期的日期(该日期包括)。然后我们按降序顺序对行进行排名,但是我们首先进行修改:如果输入日期有任何行,则它们的时间组件将被截断为零。 (DATE_TIME值仅替换为这些行的输入日期。)因此,如果输入日期有任何行,则该日期的所有行将获得rank = 1,并且所有其他行将变得更高行列。但是,如果输入日期没有行,那么该日期之前的最新行将获得rank = 1(并且该行,假设DATE_TIME中没有重复项列)。

那么外部查询的工作很简单:只保留行= ROWS,其中rank = 1.这意味着输入日期的所有行(如果有的话)或者之前的最近一行日期。

无法避免子查询外部查询结构,因为在可以在同一查询中计算排名之前评估WHERE子句。如果我们希望WHERE子句引用排名,则它必须位于外部查询中(比生成排名的查询更高级别)。

查询应该是高效的,因为优化器足够聪明,可以看到我们只想在外部查询中使用rank = 1,因此它实际上不会计算所有等级(它不会完全按顺序排列子查询行{{1 }})。当然,如果DATE_TIME上有索引,则会使用它。

你对DATE_TIME所扮演的角色没有任何说法。如果它没有任何作用,那么解决方案应该按原样运行。如果还输入了USR,则在子查询的USR子句中添加过滤器。如果您需要单独为每个WHERE生成结果,则对于相同的输入日期,请​​在USR函数的分析子句中添加PARTITION BY USR

RANK()

答案 1 :(得分:1)

下面的查询将使用窗口函数ROW_NUMBER PARTITION BY ORDER BY。它将组合(UNION ALL)等于输入日期的记录或如果未找到,则获取具有最大日期的rec。 Rownum = 1且rank = 1只能获得第一条记录。如果日期与用户输入相同,则最大日期将位于底部,不会被选中。如果未找到日期,则记录最大日期是唯一的记录,因此将显示。请参阅http://sqlfiddle.com/#!4/931c2/1上的演示。

SELECT usr as "user", date_time, valu as "value"
FROM (
SELECT usr, date_time, valu,
row_number() over (partition by trunc(date_time) 
order by date_time desc) as rnk
FROM TEST
WHERE to_char(DATE_TIME, 'yyyy-mm-dd') = '2018-05-21'
UNION ALL
SELECT usr, date_time, valu,
row_number() over (order by date_time desc) as rnk
FROM TEST) t
WHERE rnk = 1
AND rownum = 1;

答案 2 :(得分:0)

丑陋如同地狱,谁知道它在大型桌子上的行为(可能不是很好),但是 - 在一个简单的案例(基于Oracle)上有点工作。

SQL> create table test (usern varchar2(3), date_time date, hour number, value number);

Table created.

SQL> insert into test
  2    (select 'HH1', date '2018-05-20', 1, 50 from dual union
  3     select 'HH1', date '2018-05-20', 10, 50 from dual union
  4     select 'HH1', date '2018-05-20', 18, 120 from dual union
  5     select 'HH1', date '2018-05-25', 12, 10 from dual union
  6     select 'HH1', date '2018-05-26', 10, 15 from dual
  7    );

5 rows created.

SQL>

测试:

SQL> select *
  2  from test t
  3  where t.date_time = (select max(t1.date_time) from test t1
  4                       where t1.usern = t.usern
  5                         and t1.date_time <= to_date('&&date_you_enter', 'dd.mm.yyyy')
  6                      )
  7    and t.hour = (select max(case when e.it_exists = 'Y' then t.hour
  8                                  else t2.hour
  9                             end)
 10                  from test t2 left join
 11                      (select t3.usern, 'Y' it_exists
 12                       from test t3
 13                       where t3.date_time = to_date('&&date_you_enter', 'dd.mm.yyyy')
 14                      ) e on e.usern = t2.usern
 15                 )
 16  order by t.date_time, t.hour;
Enter value for date_you_enter: 20.05.2018

USE DATE_TIME        HOUR      VALUE
--- ---------- ---------- ----------
HH1 20.05.2018          1         50
HH1 20.05.2018         10         50
HH1 20.05.2018         18        120

SQL> undefine date_you_enter
SQL> /
Enter value for date_you_enter: 21.05.2018

USE DATE_TIME        HOUR      VALUE
--- ---------- ---------- ----------
HH1 20.05.2018         18        120

SQL> undefine date_you_enter
SQL> /
Enter value for date_you_enter: 25.05.2018

USE DATE_TIME        HOUR      VALUE
--- ---------- ---------- ----------
HH1 25.05.2018         12         10

SQL>

答案 3 :(得分:-2)

如果您发布SQL语句将会很有帮助。但试试这个

选择 column1,column2, 从 YourTable Date&lt; = @dateInputByUserGoesHere