【问题标题】:mysql - Get count of items where status of ALL sub-items meet the criteriamysql - 获取所有子项目的状态符合条件的项目计数
【发布时间】:2012-02-22 22:54:13
【问题描述】:

我很难为这个问题想出一个标题,但我认为对于 SQL 专家来说可能很容易。

表格:

SIMULATION: ID, SIMULATION_SET_ID, EXECUTION_STATUS
SIMULATION_SET: SET_ID 
SIMULATION_BATCH: ID
BATCH_ELEMENT: SIMULATION_BATCH_ID, SIMULATION_SET_ID

(换句话说,一个集合包含一堆模拟。一个批次通过中间表包含一堆集合。批次实际上是一个元容器,用于根据何时请求对集合进行分组,并用作容器,但本身不包含状态。)

我正在尝试返回已完成批次的计数,并且已完成批次将是其中所有模拟的执行状态为 COMPLETED 的批次。但是,我似乎得到了任何已完成模拟的批次,即使它们都不是。这是我的尝试:

SELECT COUNT(DISTINCT B.ID) 
FROM SIMULATION_BATCH B 
INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
INNER JOIN SIMULATION S ON S.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
WHERE S.EXECUTION_STATUS ='COMPLETED'";

所以回头看后,我发现这不起作用。我尝试添加 AND NOT EXISTS(SELECT...) 子句以尝试排除具有执行状态未完成的模拟但根本不起作用的批次,当任何事情发生时它始终返回一个空集正在运行。这是我添加的:

AND NOT EXISTS (SELECT SIM.ID 
FROM SIMULATION SIM 
INNER JOIN BATCH_ELEMENT BE2 ON BE2.SIMULATION_SET_ID=SIM.SIMULATION_SET_ID  
WHERE BE.SIMULATION_BATCH_ID=B.ID AND SIM.EXECUTION_STATUS != 'COMPLETED' );

感谢您对此的任何见解。我认为我需要更好地学习子查询,但我不确定。在我弄清楚如何计数之后,我需要获取包含大量信息的批次列表,但我想如果我能计数的话,我可以做到这一点。

更新:我整天都在努力,除了更多错误之外,没有取得太大进展。我在想一种更简单的方法来描述我正在寻找的内容是我想要批次中的所有模拟都满足某些标准的批次(例如状态是完整的)。当任何(至少 1 个)模拟符合标准时,我可以做到这一点,但似乎是 ALL 让我失望。任何想法将不胜感激。

【问题讨论】:

  • 您能发布一些示例数据吗?老实说,您的查询看起来应该可以工作......
  • 我会看看我是否可以获得示例数据。 not exists 子句发生的情况是,在模拟运行时我的计数为 0,而当它们全部完成时,我得到一个完整的计数。

标签: mysql sql


【解决方案1】:

我想我在子查询中看到了一个拼写错误/错误,它解释了为什么整个查询“在运行任何东西时始终返回一个空集”。

查看子查询的这一行:

WHERE BE.SIMULATION_BATCH_ID=B.ID AND SIM.EXECUTION_STATUS != 'COMPLETED' );

我认为你的本意是这样:

WHERE BE2.SIMULATION_BATCH_ID=B.ID AND SIM.EXECUTION_STATUS != 'COMPLETED' );

如果这样可以解决问题,那么您还可以尝试使用以下方式简化查询:

SELECT COUNT(DISTINCT B.ID) 
FROM SIMULATION_BATCH B 
INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
AND NOT EXISTS (
    SELECT SIM.ID
    FROM SIMULATION SIM
    INNER JOIN BATCH_ELEMENT BE2 ON BE2.SIMULATION_SET_ID=SIM.SIMULATION_SET_ID  
    WHERE BE2.SIMULATION_BATCH_ID=B.ID AND 
    SIM.EXECUTION_STATUS != 'COMPLETED' );

这假设:

  1. 一个批次总是至少有一个批次元素。
  2. 批处理元素始终具有至少一个模拟。

看起来第一种情况是正确的,因为您写道:“批处理创建时插入了 batch_element 记录。”但我不确定第二个。

祝你好运!

【讨论】:

  • 谢谢,我会试试这个,让你知道,它一直让我发疯,但后来我病了几天。如果你对错字的看法是对的,我会把头撞在墙上,因为那时我走在正确的轨道上,只是犯了一个逻辑错误
  • 嗯,这行得通,我想你找到了我的错误。所以我想这就是为什么这里的每个人都说它看起来应该可以工作,这只是一个小错误。不过,您的解决方案更清洁。谢谢!!
【解决方案2】:

我不明白为什么您的 NOT EXISTS 不起作用,但这里有一个稍微不同的方法:

SELECT COUNT(DISTINCT B.ID) 
FROM SIMULATION_BATCH B 
INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
INNER JOIN SIMULATION S ON 
    S.SIMULATION_SET_ID=BE.SIMULATION_SET_ID AND 
    S.EXECUTION_STATUS ='COMPLETED'
WHERE NOT EXISTS (
    SELECT 1
    FROM SIMULATION SUBSIM 
    WHERE 
        SUBSIM.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
        AND SUBSIM.EXECUTION_STATUS != 'COMPLETED'
)

(CAPS 对我来说有点难看,但我想保持你的约定......)

【讨论】:

  • 哈,关于 CAPS。我想在数据库方面我是老派,而且由于它必须在 Windows 和 Linux/Unix 上运行,所以它更安全。我将尝试这些修改,看看会发生什么。感谢您的意见,我会告诉您会发生什么
  • 好的,我试过这个,我得到的是这个。当我知道所有批次都完成时,我得到了 19 的计数。然后我开始新的批次,我得到了 19 的计数(到目前为止很好)。但是,一旦批次中的一个模拟完成,即使其他 23 个没有完成,我也会数到 20。也许我尝试的整个方式都是错误的。显然因为它不起作用!
  • @titania424 那么有 23 个模拟仍在进行中的批次是否有所有尚未完成的模拟的 batch_element 记录?还是只有在模拟完成后才添加batch_element 记录?
  • batch_element 记录连接 Batch 和集合。每个模拟属于一组。 batch_element 记录是在创建批次时插入的。我只是在想也许我需要一个临时表或等效表(因为我需要对已完成的批次进行类似的查询,但要获取有关它们的摘要数据,例如其中的模拟数量和基于每个开始/结束时间的持续时间模拟)。
  • 所以基本上一个批次有一堆集合,这些是通过 batch_element 表跟踪的。然后一个集合有一堆模拟。我试图通过查看所有模拟来确定批次的状态。它实际上比我所说的要复杂一些,因为有很多状态,但我正在将完成视为解决所有问题的一种手段。所以我想知道我是否需要一个临时表(或者你怎么做)来获取批次及其模拟的连接,然后从中选择以查看批次中的所有模拟是否已完成。
【解决方案3】:
SELECT COUNT(*)
FROM (SELECT B.ID 
FROM SIMULATION_BATCH B 
INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
INNER JOIN SIMULATION S ON S.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
INNER JOIN SIMULATION SC ON SC.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
WHERE SC.EXECUTION_STATUS ='COMPLETED'"
GROUP BY B.ID
HAVING COUNT(S.ID) = COUNT(SC.ID)) AS COMPLETED_BATCHES;

加入 SIMULATION 两次并在 EXECUTION_STATUS 上过滤一次 (SC)。 HAVING 子句表示我们只需要模拟数量等于已完成模拟数量的行。

编辑:对于调试,此查询应该让您了解它的工作原理:

SELECT B.ID, COUNT(S.ID) AS SIMULATION_COUNT, COUNT(SC.ID) AS COMPLETED_SIM_COUNT
FROM SIMULATION_BATCH B 
INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
INNER JOIN SIMULATION S ON S.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
INNER JOIN SIMULATION SC ON SC.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
WHERE SC.EXECUTION_STATUS ='COMPLETED'"
GROUP BY B.ID

您甚至可以将它用于子查询,跳过 HAVING,然后执行以下操作:

SELECT COUNT(ID)
FROM (
  SELECT B.ID, COUNT(S.ID) AS SIMULATION_COUNT, COUNT(SC.ID) AS COMPLETED_SIM_COUNT
  FROM SIMULATION_BATCH B 
  INNER JOIN BATCH_ELEMENT BE ON BE.SIMULATION_BATCH_ID=B.ID 
  INNER JOIN SIMULATION S ON S.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
  INNER JOIN SIMULATION SC ON SC.SIMULATION_SET_ID=BE.SIMULATION_SET_ID 
  WHERE SC.EXECUTION_STATUS ='COMPLETED'"
  GROUP BY B.ID
) AS COUNTED_BATCHES
WHERE SIMULATION_COUNT = COMPLETED_SIM_COUNT;

【讨论】:

  • 谢谢!我会试试这个。我看到了一些其他带有“HAVING”的例子,我承认不知道如何做到这一点。我只是伪装成数据库人员,必须在一个小项目上做一些事情。试用后会在这里更新。
  • 更新,好的,它不起作用,只要存在一个具有 COMPLETED 状态的模拟,批次的数量就会增加。我认为这已经很接近了,我会继续努力。
  • 我看到这个例子有一个有,但他们也使用了一些左连接。问题是我不知道他们在做什么! stackoverflow.com/questions/5352461/…
  • 左连接将返回左侧没有右侧匹配的行。在这种情况下,它会带回没有任何 SIMULATIONS 的 SIMULATION_BATCH 记录。查看我编辑的答案以获得一些调试乐趣。
  • 谢谢 - 在第一个,我为这两个计数添加了 DISTINCT,否则它会给出疯狂的数字。使用 DISTINCT 似乎可以给出正确的计数。所以这很好。我知道我越来越近了。现在尝试第二个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 2016-02-04
相关资源
最近更新 更多