I need all tickets where all the related children records are of status closed. So if one of the children is something else, I don't want the ticket in the result set.
I tried this using the antijoin patern, but my problem is that the children live in different tables.
please see this http://sqlfiddle.com/#!3/febde/8 for a example
t1: ticket t2: relatedrecord 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
results in:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 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) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
so
From this set, I only want to see ticket 1185, 1190, 1192 in the resultset. it should look like:
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
| 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) |
+----------+--------+-----------+-------+-----------------+---------------+--------+--------+--------+--------+
I tried something like:
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'
)
This results in the two lines for ticket2 AND one from ticket 3 (since it has one child closed) I'm a bit puzzeled how to solve this correctly.
I found a working answer.
See this 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);
basically it counts for each related type the number of the closed records and compares it to the total number of relatedrecords. If they are the same, all relatedrecords must be closed.