mysql - 获取所有子项的状态符合条件的项目数

时间:2012-02-22 22:54:13

标签: mysql sql

我很难为这个问题提出一个标题,但我认为对于一个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。任何想法都将不胜感激。

3 个答案:

答案 0 :(得分:2)

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

查看子查询的这一行:

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. 批处理元素始终至少有一个模拟。
  3. 看起来第一种情况是正确的,因为您写道:“在创建批处理时插入batch_element记录。”但我不确定第二个。

    祝你好运!

答案 1 :(得分:0)

我不明白为什么你的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对我来说有点难,但我想保留你的约定......)

答案 2 :(得分:0)

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;