【问题标题】:find only parent records with children of certain status across multiple tables在多个表中仅查找具有特定状态的子项的父记录
【发布时间】:2015-10-28 14:24:37
【问题描述】:

我需要所有相关子记录的状态为已关闭的所有票证。所以如果其中一个孩子是别的东西,我不希望结果集中的票。

我尝试使用反连接模式,但我的问题是孩子们住在不同的表中。

请看这个http://sqlfiddle.com/#!3/febde/8 举个例子

t1: 票 t2:相关记录 t3:孩子1 t4: 孩子1

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 有两条相关记录,均尚未关闭。 (拒绝)
  • ticket 1185 有两条相关记录,均已关闭(接受)
  • ticket 1187 有两条相关记录,一条是新的,一条是关闭的。 (拒绝)
  • 工单 1190 有一个相关记录已关闭(接受)
  • ticket 1192 有一个相关记录(不同的表)已关闭(接受)
  • ticket 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'
)

这导致票 2 的两行和票 3 的一行(因为它有一个孩子关闭) 我有点困惑如何正确解决这个问题。

【问题讨论】:

  • 这是一个很好的起点。 spaghettidba.com/2015/04/24/…
  • 我添加了一个带有示例数据的 sqlfiddle
  • 这是 mysql 还是 sql server 的?您的小提琴是 mysql,但您已将其标记为 sqlserver。
  • 我不确定这对这个问题是否重要。对于 oracle、sqlserver 和 db2,我可能需要类似的东西
  • 我不知道如何在 mysql 中执行此操作,但在 sqlserver 中您可以使用递归 cte 遍历整个层次结构。

标签: sql sql-server join anti-join


【解决方案1】:

仍然不完全确定您想要什么结果,但我认为可能就是这样。

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

【讨论】:

  • 不,这是不正确的。它还将显示包含已关闭儿童和不同身份儿童的门票。在这种情况下,它将包括不正确的 1187。 sqlfiddle.com/#!3/febde/7
  • 我用我想要从该数据中获取的结果集更新了帖子。
  • 对,但我需要解释为什么。我在猜测业务规则。
【解决方案2】:

我找到了一个可行的答案。

查看这个 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);

基本上,它会为每个相关类型计算已关闭记录的数量,并将其与相关记录的总数进行比较。如果它们相同,则必须关闭所有相关记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 2021-04-12
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多