在多个表中仅查找具有 children 特定状态的 parent 记录
find only parent records with children of certain status across multiple tables
我需要所有相关 children 记录都处于关闭状态的所有工单。因此,如果 children 之一是其他东西,我不希望结果集中的票。
我尝试使用反连接模式,但我的问题是 children 生活在不同的 tables。
请看这个http://sqlfiddle.com/#!3/febde/8
例如
t1: 门票
t2:相关记录
t3: child1
t4: child1
select ticket.ticketid, rr.relatedrecordkey, rr.relatedrecordclass, c1.id, c1.status, c2.id, c2.status
from ticket
inner join relatedrecord rr on rr.recordkey = ticket.ticketid and rr.class = ticket.class
left join child1 c1 on c1.id = rr.relatedreckey and c1.class = rr.relatedrecclass
left join child2 c2 on c2.id = rr.relatedreckey and c2.class = rr.relatedrecclass
结果:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| ticketid | status | RECORDKEY | class | RELATEDRECCLASS | relatedreckey | id | status | id | status |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 1183 | NEW | 1183 | SR | WORKORDER | 1238 | 1238 | NEW | (null) | (null) |
| 1183 | NEW | 1183 | SR | SR | 1184 | (null) | (null) | 1184 | NEW |
| 1185 | NEW | 1185 | SR | WORKORDER | 1239 | 1239 | CLOSE | (null) | (null) |
| 1185 | NEW | 1185 | SR | SR | 1186 | (null) | (null) | 1186 | CLOSE |
| 1187 | NEW | 1187 | SR | WORKORDER | 1240 | 1240 | CLOSE | (null) | (null) |
| 1187 | NEW | 1187 | SR | SR | 1188 | (null) | (null) | 1188 | NEW |
| 1190 | NEW | 1190 | SR | SR | 1191 | (null) | (null) | 1191 | CLOSE |
| 1192 | NEW | 1192 | SR | WORKORDER | 1241 | 1241 | CLOSE | (null) | (null) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
所以
- ticket 1183有两条相关记录,均未关闭。 (拒绝)
- 工单1185有两条相关记录,均已关闭(接受)
- ticket 1187有两条相关记录,一条是new,一条是closed。 (拒绝)
- 工单 1190 有一条相关记录已关闭(接受)
- 工单 1192 有一条相关记录(不同 table)已关闭(接受)
- 工单1189无相关记录(拒绝)
从这个集合中,我只想在结果集中看到票 1185、1190、1192。
它应该看起来像:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| ticketid | status | RECORDKEY | class | RELATEDRECCLASS | relatedreckey | id | status | id | status |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 1185 | NEW | 1185 | SR | WORKORDER | 1239 | 1239 | CLOSE | (null) | (null) |
| 1185 | NEW | 1185 | SR | SR | 1186 | (null) | (null) | 1186 | CLOSE |
| 1190 | NEW | 1190 | SR | SR | 1191 | (null) | (null) | 1191 | CLOSE |
| 1192 | NEW | 1192 | SR | WORKORDER | 1241 | 1241 | CLOSE | (null) | (null) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
我试过类似的方法:
select ticket.ticketid, rr.relatedrecordkey, rr.relatedrecordclass, c1.id, c1.status, c2.id, c2.status
from ticket
inner join relatedrecord rr on rr.recordkey = ticket.ticketid and rr.class = ticket.class
where not exists (
select 1 from child1 c1
where c1.id = rr.relatedreckey and c1.class = rr.relatedrecclass
and c1.status <> 'CLOSE'
) and not exists (
select 1 from child2 c2
where c2.id = rr.relatedreckey and c2.class = rr.relatedrecclass
and c2.status <> 'CLOSE'
)
这导致 ticket2 的两行和来自 ticket 3 的一行(因为它有一个 child 已关闭)
我有点困惑如何正确解决这个问题。
仍然不太确定你想要什么结果,但我想可能就是这样。
select *
from
(
select t.ticketid
from ticket t
join relatedrecord rr on rr.recordkey = t.ticketid and rr.class = t.class
join child1 c1 on c1.id = rr.relatedreckey
and c1.class = rr.relatedrecclass
and c1.status = 'CLOSE'
group by t.ticketid
having MAX(c1.status) = MIN(c1.status)
UNION ALL
select t.ticketid
from ticket t
join relatedrecord rr on rr.recordkey = t.ticketid and rr.class = t.class
join child2 c2 on c2.id = rr.relatedreckey
and c2.class = rr.relatedrecclass
and c2.status = 'CLOSE'
group by t.ticketid
having MAX(c2.status) = MIN(c2.status)
) x
group by ticketid
我找到了有效的答案。
查看此 sqlfiddle:http://sqlfiddle.com/#!3/febde/24
SELECT ticket.ticketid,
count(rr.relatedreckey) AS children,
count(wo.id) AS wo,
count(tt.id) AS sr
FROM ticket
INNER JOIN relatedrecord rr ON rr.recordkey = ticket.ticketid
AND rr.class = ticket.class
LEFT JOIN child1 wo ON wo.id = rr.relatedreckey
AND wo.class = rr.relatedrecclass
AND wo.status = 'CLOSE'
LEFT JOIN child2 tt ON tt.id = rr.relatedreckey
AND tt.class = rr.relatedrecclass
AND tt.status = 'CLOSE'
GROUP BY ticket.ticketid
HAVING (count(wo.id) + count(tt.id)) = count(rr.relatedreckey);
基本上它会计算每个相关类型的已关闭记录的数量,并将其与相关记录的总数进行比较。如果相同,则必须关闭所有相关记录。
我需要所有相关 children 记录都处于关闭状态的所有工单。因此,如果 children 之一是其他东西,我不希望结果集中的票。
我尝试使用反连接模式,但我的问题是 children 生活在不同的 tables。
请看这个http://sqlfiddle.com/#!3/febde/8 例如
t1: 门票 t2:相关记录 t3: child1 t4: child1
select ticket.ticketid, rr.relatedrecordkey, rr.relatedrecordclass, c1.id, c1.status, c2.id, c2.status
from ticket
inner join relatedrecord rr on rr.recordkey = ticket.ticketid and rr.class = ticket.class
left join child1 c1 on c1.id = rr.relatedreckey and c1.class = rr.relatedrecclass
left join child2 c2 on c2.id = rr.relatedreckey and c2.class = rr.relatedrecclass
结果:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| ticketid | status | RECORDKEY | class | RELATEDRECCLASS | relatedreckey | id | status | id | status |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 1183 | NEW | 1183 | SR | WORKORDER | 1238 | 1238 | NEW | (null) | (null) |
| 1183 | NEW | 1183 | SR | SR | 1184 | (null) | (null) | 1184 | NEW |
| 1185 | NEW | 1185 | SR | WORKORDER | 1239 | 1239 | CLOSE | (null) | (null) |
| 1185 | NEW | 1185 | SR | SR | 1186 | (null) | (null) | 1186 | CLOSE |
| 1187 | NEW | 1187 | SR | WORKORDER | 1240 | 1240 | CLOSE | (null) | (null) |
| 1187 | NEW | 1187 | SR | SR | 1188 | (null) | (null) | 1188 | NEW |
| 1190 | NEW | 1190 | SR | SR | 1191 | (null) | (null) | 1191 | CLOSE |
| 1192 | NEW | 1192 | SR | WORKORDER | 1241 | 1241 | CLOSE | (null) | (null) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
所以
- ticket 1183有两条相关记录,均未关闭。 (拒绝)
- 工单1185有两条相关记录,均已关闭(接受)
- ticket 1187有两条相关记录,一条是new,一条是closed。 (拒绝)
- 工单 1190 有一条相关记录已关闭(接受)
- 工单 1192 有一条相关记录(不同 table)已关闭(接受)
- 工单1189无相关记录(拒绝)
从这个集合中,我只想在结果集中看到票 1185、1190、1192。 它应该看起来像:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| ticketid | status | RECORDKEY | class | RELATEDRECCLASS | relatedreckey | id | status | id | status |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 1185 | NEW | 1185 | SR | WORKORDER | 1239 | 1239 | CLOSE | (null) | (null) |
| 1185 | NEW | 1185 | SR | SR | 1186 | (null) | (null) | 1186 | CLOSE |
| 1190 | NEW | 1190 | SR | SR | 1191 | (null) | (null) | 1191 | CLOSE |
| 1192 | NEW | 1192 | SR | WORKORDER | 1241 | 1241 | CLOSE | (null) | (null) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
我试过类似的方法:
select ticket.ticketid, rr.relatedrecordkey, rr.relatedrecordclass, c1.id, c1.status, c2.id, c2.status
from ticket
inner join relatedrecord rr on rr.recordkey = ticket.ticketid and rr.class = ticket.class
where not exists (
select 1 from child1 c1
where c1.id = rr.relatedreckey and c1.class = rr.relatedrecclass
and c1.status <> 'CLOSE'
) and not exists (
select 1 from child2 c2
where c2.id = rr.relatedreckey and c2.class = rr.relatedrecclass
and c2.status <> 'CLOSE'
)
这导致 ticket2 的两行和来自 ticket 3 的一行(因为它有一个 child 已关闭) 我有点困惑如何正确解决这个问题。
仍然不太确定你想要什么结果,但我想可能就是这样。
select *
from
(
select t.ticketid
from ticket t
join relatedrecord rr on rr.recordkey = t.ticketid and rr.class = t.class
join child1 c1 on c1.id = rr.relatedreckey
and c1.class = rr.relatedrecclass
and c1.status = 'CLOSE'
group by t.ticketid
having MAX(c1.status) = MIN(c1.status)
UNION ALL
select t.ticketid
from ticket t
join relatedrecord rr on rr.recordkey = t.ticketid and rr.class = t.class
join child2 c2 on c2.id = rr.relatedreckey
and c2.class = rr.relatedrecclass
and c2.status = 'CLOSE'
group by t.ticketid
having MAX(c2.status) = MIN(c2.status)
) x
group by ticketid
我找到了有效的答案。
查看此 sqlfiddle:http://sqlfiddle.com/#!3/febde/24
SELECT ticket.ticketid,
count(rr.relatedreckey) AS children,
count(wo.id) AS wo,
count(tt.id) AS sr
FROM ticket
INNER JOIN relatedrecord rr ON rr.recordkey = ticket.ticketid
AND rr.class = ticket.class
LEFT JOIN child1 wo ON wo.id = rr.relatedreckey
AND wo.class = rr.relatedrecclass
AND wo.status = 'CLOSE'
LEFT JOIN child2 tt ON tt.id = rr.relatedreckey
AND tt.class = rr.relatedrecclass
AND tt.status = 'CLOSE'
GROUP BY ticket.ticketid
HAVING (count(wo.id) + count(tt.id)) = count(rr.relatedreckey);
基本上它会计算每个相关类型的已关闭记录的数量,并将其与相关记录的总数进行比较。如果相同,则必须关闭所有相关记录。