[英]Oracle SQL compare rows of the same table
Table: 表:
Date shopId amount 17-MAY-19 1 100 17-MAY-19 2 20 16-MAY-19 2 20 17-APR-19 1 50
I need to find those records of the same table according to the requirements: 我需要根据要求找到同一表的那些记录:
Given a date eg sysdate, find the record with that date for each shopId ( the date is unique for each shopId) and also the pre-30day record. 给定日期,例如sysdate,找到每个shopId带有该日期的记录(每个shopId的日期是唯一的)以及30天之前的记录。
Compare the amount of the 2 records to see if the absolute % diff is greater than 5 (I use 0.05 instead of % in the code below). 比较2条记录的数量,以查看diff的绝对百分比是否大于5(我在下面的代码中使用0.05代替%)。
If both the 2 records exist and the % diff is matched, the record should be in the result set. 如果两个记录都存在并且%diff匹配,则该记录应在结果集中。
Do this for all shopId
s and return the result set. 对所有shopId
执行此操作,然后返回结果集。
I am able to retrieve the records and then do the comparison in backend languages such as JAVA and PHP but I wonder if it is better to do it by SQL which I'm not familiar with. 我能够检索记录,然后使用JAVA和PHP等后端语言进行比较,但是我想知道用不熟悉的SQL进行比较是否更好。
select *
from table t1
inner join table t2 on t1.shopId = t2.shopId
WHERE t1.ordertime = sysdate
and t2.ordertime = sysdate - 30
and abs( (t1.amount - t2.amount) / t2.amount > 0.05 )
Expected result should be: 预期结果应为:
Table: shopId Date1 amount1 Date2 amount2 1 17-MAY-19 100 17-APR-19 50
Please help, thank you. 请帮忙,谢谢。
you should use trunc
function on sysdate
, because sysdate always contains the current date and time 您应该在sysdate
上使用trunc
函数,因为sysdate始终包含当前日期和时间
with tab as(
select to_date('17.05.2019','dd.mm.yyyy') as dat, 1 as shopid, 100 as amount from dual union all
select to_date('17.05.2019','dd.mm.yyyy') as dat, 2 as shopid, 20 as amount from dual union all
select to_date('16.05.2019','dd.mm.yyyy') as dat, 2 as shopid, 20 as amount from dual union all
select to_date('17.04.2019','dd.mm.yyyy') as dat, 1 as shopid, 50 as amount from dual
)
select *
from tab t1
join tab t2 on t1.shopid = t2.shopid
WHERE t1.dat = trunc(sysdate)
and t2.dat = trunc(sysdate - 30)
and (t1.amount - t2.amount) / t2.amount > 0.05
An alternative to joins would be to use the LAG
analytic function, eg: 联接的替代方法是使用LAG
分析功能,例如:
WITH your_table AS (SELECT to_date('17.05.2019','dd.mm.yyyy') dt, 1 shopid, 100 amount FROM dual UNION ALL
SELECT to_date('17.05.2019','dd.mm.yyyy') dt, 2 shopid, 20 amount FROM dual UNION ALL
SELECT to_date('16.05.2019','dd.mm.yyyy') dt, 2 shopid, 20 amount FROM dual UNION ALL
SELECT to_date('17.04.2019','dd.mm.yyyy') dt, 1 shopid, 50 amount FROM dual)
SELECT shopid,
date1,
amount1,
date2,
amount2
FROM (SELECT shopid,
dt date1,
amount amount1,
LAG(dt) OVER (PARTITION BY shopid ORDER BY dt) date2,
LAG(amount) OVER (PARTITION BY shopid ORDER BY dt) amount2
FROM your_table
WHERE dt IN (TRUNC(SYSDATE), TRUNC(SYSDATE) - 30))
WHERE amount1 > amount2 * 1.05;
SHOPID DATE1 AMOUNT1 DATE2 AMOUNT2
---------- ----------- ---------- ----------- ----------
1 17/05/2019 100 17/04/2019 50
Whether this is faster than the join version is up to you to test and decide. 这是否比联接版本快要由您测试和决定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.