我知道stackoverflow会帮助我,除了知道什么是“最喜欢的编程卡通”:P
这是接受的答案: Bill Karwin
感谢大家的帮助(我想双倍投票给你们)
我的查询最终结果如此(这是真实的)
SELECT
accepted.folio,
COALESCE( inprog.activityin, accepted.activityin ) as activityin,
inprog.participantin,
accepted.completiondate
FROM performance accepted
LEFT OUTER JOIN performance inprog
ON( accepted.folio = inprog.folio
AND inprog.ACTIVITYIN
IN ( 4, 435 ) -- both are ids for inprogress
AND inprog.PARTICIPANTIN != 1 ) -- Ignore the "bot" participant
LEFT OUTER JOIN performance closed
ON( accepted.folio = closed.folio
AND closed.ACTIVITYIN IN ( 10,436, 4, 430 ) ) -- all these are closed or cancelled
WHERE accepted.ACTIVITYIN IN ( 3, 429 ) --- both are id for new
AND accepted.folio IS NOT NULL
AND closed.folio IS NULL;
现在我只需要与其他表一起加入人类可读的报告。
<小时/> 原始帖子
您好。
我挣扎了大约6个小时。现在有一个数据库查询(我的长期克星)
我有一个包含以下字段的数据表:
table performance(
identifier varchar,
activity number,
participant number,
closedate date,
)
用于跟踪故障单的历史记录
标识符:是一个客户ID,如(NAF0000001)
活动:是票证所在地的fk(新的,in_progress,拒绝,关闭等)
参与者:当时正在参加门票的人员
关闭:是该活动结束的日期。
编辑:我应该说“完成日期”而不是关闭。这是活动完成的日期,当票证关闭时不需要。
例如,典型的历史可能是这样的:
identifier|activity|participant|closedate ------------------------------------------- NA00000001| 1| 1|2008/10/08 15:00| ------------------------------------------- NA00000001| 2| 2|2008/10/08 15:20| ------------------------------------------- NA00000001| 3| 2|2008/10/08 15:40| ------------------------------------------- NA00000001| 4| 4|2008/10/08 17:05| -------------------------------------------
参与者1 = jonh,2 = scott,3 =迈克,4 =抢劫
和活动1 =新的,2 =进行中,3 = waitingforapproval,4 =关闭
等。还有其他几十个不相干的信息。
我的问题如下。
我已设法创建一个查询,我可以知道何时打开和关闭故障单
就像这样:
select
a.identifier,
a.participant,
a.closedate as start,
b.closedate as finish
from
performance a,
performance b
where
a.activity = 1 -- new
and b.activity = 4 -- closed
and a.identifier = b.identifier
但我不知道哪些门票不已关闭,以及谁在参加。
到目前为止,我有这样的事情:
select
a.identifier,
a.participant,
a.closedate as start
from
performance a
where
a.activity = 1 -- new
and a.identifier not in ( select identifier from performance where activity = 4 ) --closed
那是给我所有有开始的人(新= 1)但未关闭(关闭= 4)
但这里的一个大问题是它打印了打开票证的参与者,但我需要参与者的参与者。所以我在查询中添加了“inprogress”活动。
select
a.identifier,
a.participant,
a.closedate as start
from
performance a,
performance b
where
a.activity = 1 -- new
and a.identifier not in ( select identifier from performance where activity = 4 ) --closed
and b.identifier = a.identifier
and b.activity = 2 -- inprogress..
但并非所有“new”中的行都是“inprogress”,并且使用该查询我将丢弃所有这些行。
我需要的是显示所有“inprogress”参与者,如果票证不是“inprogress”,它将显示为空。
像
这样的东西identifier|activity|participant|closedate ------------------------------------------- NA00000002| 1| |2008/10/08 15:00| ------------------------------------------- NA00000003| 1| |2008/10/08 15:20| ------------------------------------------- NA00000004| 1| |2008/10/08 15:40| ------------------------------------------- NA00000005| 2| 4|2008/10/08 15:40| ------------------------------------------- NA00000006| 2| 4|2008/10/08 15:40|
在这种情况下
NA002,NA003和NA004处于“新”状态,因此不会显示参与者
虽然
NA005和NA006正在“inprgress(act = 2)”并且他们正在参加抢劫(参与者4)
所以我记得有一个叫做左外连接的东西或类似的东西,但我从来都不理解它。我想知道的是如何获取“inprogress”和“new”且未关闭的标识符。
可能稍稍休息会帮助我清醒一下。如果有人知道怎么做,我会很感激。
顺便说一句,我试过了:
select
a.identifier,
a.participant,
a.closedate as start
from
performance a
left outer join
performance b
on
b.identifier = a.identifier
where
a.activity = 1 -- new
and a.identifier not in ( select identifier from performance where activity = 4 ) --closed
and b.activity = 2 -- inprogress..
但是给了我与前一个相同的结果(只删除了“新”记录)
答案 0 :(得分:3)
通常,更好的方法是使用EXISTS。第一个是:
select * from performance p1
where not exists
( select * from performance p2
where p2.identifier = p1.identifier and p2.activity = 4 )
这种方式允许您对performance.identifier执行键控查找,而不必在(select identifier from performance where activity=4)
中构建大量标识符列表。
答案 1 :(得分:3)
尝试这样的事情(我还没有测试过):
SELECT p_new.identifier, COALESCE(p_inprog.activity, p_new.activity) AS activity,
p_inprog.participant, COALESCE(p_inprog.closedate, p_new.closedate) AS closedate
FROM performance p_new
LEFT OUTER JOIN performance p_inprog
ON (p_new.identifier = p_inprog.identifier AND p_inprog.activity = 2)
LEFT OUTER JOIN performance p_closed
ON (p_new.identifier = p_closed.identifier AND p_closed.activity = 4)
WHERE p_new.activity = 1
AND p_closed.identifier IS NULL;
我认为人们相信外部联合比实际更难。例如:
A LEFT OUTER JOIN B ON (...condition...)
这将返回A中的所有行,无论B中是否存在任何匹配的行。如果B中没有匹配的行,则将所有列B. *视为在该行的结果集中为NULL。连接条件可以是B中的行必须满足的表达式,否则它不包含在连接中。因此,A中的更多行将是独奏。
答案 2 :(得分:2)
我认为应该这样做。
第一部分获取所有新记录,未关闭且未进行记录。第二部分获取所有正在进行的记录。然后我们将它们连接在一起,我们也可以通过在此查询周围包装“SELECT * FROM”来按标识符排序。
select
a.identifier,
a.participant,
a.closedate as start
from
performance a
where
a.activity = 1
and not exists ( select identifier
from performance b
where b.activity = 4
and b.identifier = a.identifier)
and not exists ( select identifier
from performance c
where c.activity = 2
and c.identifier = a.identifier)
UNION ALL
select
a.identifier,
a.participant,
a.closedate as start
from
performance a
where
a.activity = 2
and not exists ( select identifier
from performance b
where b.activity = 4
and b.identifier = a.identifier);
答案 3 :(得分:1)
我建议你想要的是最早的记录(可能,但不一定是活动= 1的记录)和最近的记录(不论活动编号)。如果最近记录的活动为4,则票证将关闭。否则,参与者是票证的当前持有者。如果可以重新打开故障单,只需在activity = 4上匹配就会引入潜在的错误。
实际上,根据你的例子,你甚至可能不需要最早的记录。如下:
SELECT
identifier,
activity,
participant,
closedate
FROM
performance a
WHERE
(a.identifier, a.closedate) in
(select b.identifier, max(b.closedate)
from performance b
group by b.identifier
)
;
答案 4 :(得分:1)
这个怎么样:
SELECT * FROM (
SELECT identifier,
MAX(activity) activity,
MAX(participant) KEEP (DENSE_RANK LAST ORDER BY activity)
FROM performance
GROUP BY identifier
)
WHERE activity in (1,2)
内部查询为每张故障单及其相应的参与者提供最新活动。外部查询将其过滤到活动为“新”或“正在进行”的那些。
我喜欢DENSE_RANK功能。
答案 5 :(得分:0)
首先,如果您的客户可以同时打开多张票,则可能会遇到设计问题。理想情况下,您应该拥有ticket_id,然后您可以使用ticket_id而不是标识符来执行Andy的查询。
答案 6 :(得分:0)
什么门票没有关闭:
select identifier as closed_identifier
from performance where identifier not exists
(select identifier from performance where activity=4)
正在参加的门票:
select identifier as inprogress_identifier, participant performance
from performance where activity=2
未关闭的门票,其参与者正在参加:
select * from
(select identifier as notclosed_identifier
from performance where identifier not exists
(select identifier from performance where activity=4)) closed
left join
(select identifier as inprogress_identifier, participant performance
from performance where activity=2) attended
on notclosed_identifier=inprogress_identifier
答案 7 :(得分:0)
可能您可以使用此类查询作为起点。
select x.identifier,
max(x.p_1) as new_participant, max(x.c_1) as new_date,
max(x.p_2) as inprogress_participant, max(x.c_2) as inprogress_date,
max(x.p_3) as approval_participant, max(x.c_3) as approval_date,
max(x.p_4) as closing_participant, max(x.c_4) as closing_date
from (
select a.identifier,
decode (activity, 1, participant, null) as p_1, decode (activity, 1, closedate, null) as c_1,
decode (activity, 2, participant, null) as p_2, decode (activity, 2, closedate, null) as c_2,
decode (activity, 3, participant, null) as p_3, decode (activity, 3, closedate, null) as c_3,
decode (activity, 4, participant, null) as p_4, decode (activity, 4, closedate, null) as c_4
from performance a
) x
group by x.identifier
我们的想法是将您的表从一行序列化为字段,并基于它创建一个视图。 您可以根据此视图创建报告。
此致
答案 8 :(得分:0)
只是快速了解其他人可能会建立的(未经测试,但我希望这个想法能够实现):
首先,选择所有尚未结束的活动(由其他人发布):
select id
from performance p1 where identifier not exists
(select * from performance p2 where activity=4 and p1.id=p2.id)
然后,您可以通过在select子句中添加子查询来添加参加活动的人员:
select id,
(select participant
from performance p3
where p3.activity=3 and p1.id=p2.id)
from performance p1 where identifier not exists
(select * from performance p2 where activity=4 and p1.id=p2.id)
如果此id没有活动3记录,则子查询返回null,这正是我们所需要的。
希望这会有所帮助 - 如有必要请扩展。