我有一组数据,我将日期的用户输入传递给表格。
我要做的是设置逻辑:
这是原始表格:
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
我不确定如何找到这个最近的价值。
任何帮助将不胜感激,谢谢!
答案 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