问题陈述:
选择所有商店名称,其状态,电话号码,生效日期 其电话号码已从2003年更改为现在。
架构是
store_name,phone number , start_date , status
示例行
abc 1234 30-DEC-2011 open
abc 3433 04-Jan-2012 close
bbb 4444 30-Jan-2010 open
bbb 4444 31-Jan-2011 open
输出
abc 1234 open 30-DEC-3011 till 3-Jan-2012
abc 3433 close 04-Jan-2012 till date
我也很好,输出中有两行,排序的开始日期如
abc 1234 30-DEC-2011 open
abc 3433 04-Jan-2012 close
不应报告 bbb
,因为电话号码没有变化。我们只应报告电话号码已更改的商店。
有人可以帮我解决这个关于Oracle的问题吗?我想通过使用相关查询可以完成,但我不知道如何构建一个。
请注意,我的表有大约3154953条记录,因此我还需要确保相关查询不会在很长一段时间内锁定表。这甚至可以用于Oracle吗?
谢谢!
APC的回答对我而言只是因为我在结果中看到了很多重复。
输入:
select store_name,phone_number,start_date, status where store_name=abc;
返回
STORE_name Phone number start_date STATUS
---------------- ---------------- ----------- ----------
abc 122 18-JAN-2011 open
abc 122 18-JAN-2011 open
abc 122 18-JAN-2011 close
运行查询会给我以下输出。
abc 122 open from 18-JAN-2011 to 17-JAN-2011
abc 122 open from 18-JAN-2011 to 17-JAN-2011
abc 122 close from 18-JAN-2011 to date
你能解释为什么以及在哪里错过了吗?
答案 0 :(得分:2)
我认为这是针对Oracle而不是MySQL,因为我的解决方案使用了一些魔术技巧,我很确定这些技巧在MySQL中不可用。第一个是Common Table Expression来获取一个我们可以使用多次的结果集。第二个是使用LEAD()分析函数来“预测”下一行中的值。
所以,这是查询:
with a as ( select store_name
, phone_number
, status
, start_date
, lead (start_date, 1, trunc(sysdate)) over (partition by store_name
order by start_date) as next_date
, lead (phone_number, 1, null) over (partition by store_name
order by start_date) as next_number
from your_table
where start_date >= date '2003-01-01' )
select a.store_name
, a.phone_number
, case when a.next_date != trunc(sysdate) then
a.status||' from '|| a.start_date ||' to '||to_char(a.next_date - 1)
else a.status||' from '||a.start_date ||' to date'
end as status_text
from a
where a.store_name in (
select store_name
from a
where phone_number != next_number)
order by a.store_name, a.start_date
/
这是它的输出:
SQL> r
1 with a as ( select store_name
...
22 order by a.store_name, a.start_date
23 /
STORE_NAME PHONE_NUMBER STATUS_TEXT
-------------------- ------------ --------------------------------
abc 1234 open from 30-DEC-11 to 03-JAN-12
abc 3433 close from 04-JAN-12 to date
2 rows selected.
SQL>
至于这句话:
“因此我还需要确保相关查询不会锁定 表很多时间“
在Oracle中无关紧要,因为读取不会阻止其他读取。也没有写到这一点。
答案 1 :(得分:0)
这将是
的内容select * from table0 as q0 join
(
select min(date) from table0 as q1 where q1.store_name = q0.store_name
) as q2 on q2.store_name = q0.store_name
left join
(
select max(date) from table0 as q1 where q1.store_name = q0.store_name
) as q3 on q3.store_name = q0.store_name
这不太正确,因为我没有在我面前使用MySQL,但是它的内容就是这样。