我有一个包含三个字段的表:ID
,date
和action
。 action
的三个可能值为X
,Y
和Z
。我想要一个查询,对于表格中的每个ID
,其中有Z
行的行,将返回同一ID
的最新行{{1}动作,如果存在的话。
这是我想在MySQL中做的事情。我复制并粘贴了sqlfiddle.com的代码,所以我知道它有效。
X
我不能在Oracle中使用create table a (id int,
date int,
action varchar(1));
insert into a values(1, 1, 'X');
insert into a values(1, 2, 'X');
insert into a values(1, 3, 'Z');
insert into a values(2, 1, 'X');
insert into a values(2, 2, 'Y');
insert into a values(2, 3, 'Y');
insert into a values(2, 4, 'Z');
insert into a values(3, 1, 'X');
insert into a values(3, 2, 'Y');
insert into a values(3, 3, 'X');
insert into a values(3, 4, 'Z');
insert into a values(4, 3, 'X');
SELECT a.id,
max(a.date) as Xdate,
b.date as Zdate,
a.action FROM a,
(SELECT * FROM a WHERE a.action = 'Z') b
WHERE
a.date < b.date AND
a.ID = b.ID AND
a.action = 'X'
GROUP BY a.id;
子句和其他类似的字段,所以我做了一个嵌套的子查询,它分别找到了每个ID的最大日期,但它很慢(我希望得到大约10 ^ 5行)我希望有更好的方法来做到这一点会更快。 (我现在无法发布我的实际Oracle查询,因为它不能在SQLfiddle中运行;它一直在抱怨行被明确定义。)
上面的查询可以以某种方式在Oracle中工作吗?如果没有,是否有相同的方法可以在合理的时间内运行?
答案 0 :(得分:2)
这有效(尽管可以简化):
SELECT a.id,
max(a."date") as Xdate,
b."date" as Zdate,
a.action
FROM a INNER JOIN
(SELECT *
FROM a
WHERE a.action = 'Z') b
ON a.ID = b.ID
WHERE a."date" < b."date"
AND a.action = 'X'
GROUP BY a.id, b."date", a.action
请注意,您需要在保留字周围使用"
- 在本例中为date
列。您还需要将所有字段添加到GROUP BY
子句中。 MySQL允许它没有,但Oracle没有。
编辑,简化版:
SELECT a.Id, max(a."date"), b."date", a.action
FROM a
INNER JOIN a b ON a.Id = b.Id AND b.action = 'Z'
WHERE a.action = 'X'
AND a."date" < b."date"
GROUP BY a.Id, b."date", a.action
答案 1 :(得分:1)
这里有其他解决方案:
WITH temp AS (
SELECT a.id, a.date_f, a.action FROM a WHERE a.action = 'Z'
)
SELECT a.id,
max(a.date_f) as Xdate,
temp.date_f as Zdate,
a.action
FROM a
INNER JOIN temp ON temp.id = a.id AND a.date_f < temp.date_f
WHERE a.action = 'X'
GROUP BY a.id,temp.date_f,a.action;
注意:date_f是字段日期。 的 SQL Fiddle Demo 强>
答案 2 :(得分:0)
尝试在MySQL和Oracle之间进行的一个问题是Oracle功能更强大。
您可以使用Oracle中的分析功能解决您的问题。这些在MySQL中不可用。
以下是Oracle解决方案:
select a.id, a.thedate as Xdate, a.ZDate
from (select a.*,
min(case when action = 'Z' then thedate end) over
(partition by id
order by thedate
rows between current row and unbounded following
) as Zdate,
row_number() over (partition by id, action
order by thedate desc
) as seqnum
from a
) a
where a.action = 'X' and a.seqnum = 1;
您可以在SQL Fiddle here上看到它。