将记录分组到一个临时表中

时间:2008-12-30 15:31:45

标签: sql

我有一个表,其中一列有重复记录,但其他列是不同的。所以像这样

代码子代码版本状态

1234 D1 1 A

1234 D1 0 P

1234 DA 1 A

1234 DB 1 P

5678 BB 1 A

5678 BB 0 P

5678 BP 1 A

5678 BJ 1 A

0987 HH 1 A

所以在上表中。子代码和版本是唯一值,而代码重复。我想将上表中的记录转移到临时表中。只有我想要传输的记录才是代码的所有子代码都具有“A”的状态,我只想在临时表中使用它们一次。

所以从上面的例子开始。临时表应该只有 5678和0987,因为所有相对于5678的子节点都具有'A'状态,并且0987的所有子节点(它只有一个)具有A的状态。由于其子代码'DB'的状态为'P'

我很感激任何帮助!

4 个答案:

答案 0 :(得分:1)

关于版本栏是否发挥作用,有点不清楚。例如,您是否只想考虑具有最大版本的行,或者如果任何子类具有“A”,则它是否计数。以5678,例如BB为例,其中版本1具有“A”而版本0具有“B”。是否包含5678因为至少有一个子代码BB具有“A”或者是因为版本1具有“A”。

以下代码假定您希望所有代码中每个子代码至少有一个“A”,无论版本如何。

SELECT
    T1.code,
    T1.subcode,
    T1.version,
    T1.status
FROM
    MyTable T1
WHERE
    (
      SELECT COUNT(DISTINCT subcode)
      FROM MyTable T2
      WHERE T2.code = T1.code
    ) =
    (
      SELECT COUNT(DISTINCT subcode)
      FROM MyTable T3
      WHERE T3.code = T1.code AND T3.status = 'A'
    )

如果你的桌子很大,表现可能会很糟糕。我会尝试提出一个可能会有更好性能的查询,因为这是我的头脑。

另外,如果你解释问题的全部范围,也许我们可以找到摆脱那个临时表的方法......;)

以下是两种可能的方法。仍然有很多子查询,但它们看起来会比上面的方法表现更好。它们都非常相似,虽然第二个在我的数据库中有更好的查询计划。当然,数据有限,没有索引,这不是一个很好的测试。您应该尝试所有方法,看看哪种方法最适合您的数据库。

SELECT
    T1.code,
    T1.subcode,
    T1.version,
    T1.status
FROM
    MyTable T1
WHERE
    EXISTS
    (
        SELECT *
        FROM MyTable T2
        WHERE T2.code = T1.code
          AND T2.status = 'A'
    ) AND
    NOT EXISTS
    (
        SELECT *
        FROM MyTable T3
        LEFT OUTER JOIN MyTable T4 ON
            T4.code = T3.code AND
            T4.subcode = T3.subcode AND
            T4.status = 'A'
        WHERE T3.code = T1.code
          AND T3.status <> 'A'
          AND T4.code IS NULL
    )

SELECT
    T1.code,
    T1.subcode,
    T1.version,
    T1.status
FROM
    MyTable T1
WHERE
    EXISTS
    (
        SELECT *
        FROM MyTable T2
        WHERE T2.code = T1.code
          AND T2.status = 'A'
    ) AND
    NOT EXISTS
    (
        SELECT *
        FROM MyTable T3
        WHERE T3.code = T1.code
          AND T3.status <> 'A'
          AND NOT EXISTS
            (
                SELECT *
                FROM MyTable T4
                WHERE T4.code = T3.code
                  AND T4.subcode = T3.subcode
                  AND T4.status = 'A'
            )
    )

答案 1 :(得分:1)

这是我的解决方案

SELECT Code
FROM
(
  SELECT
    Code,
    COUNT(SubCode) as SubCodeCount
    SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END)
      as SubCodeCountWithA
  FROM
  (
    SELECT
      Code,
      SubCode,
      SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END)
        as ACount
    FROM CodeTable
    GROUP BY Code, SubCode
  ) sub
  GROUP BY Code
) sub2
WHERE SubCodeCountWithA = SubCodeCount

让我们从内到外打破它。

    SELECT
      Code,
      SubCode,
      SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END)
        as ACount
    FROM CodeTable
    GROUP BY Code, SubCode

对代码和子代码进行分组(每行是代码和子代码的不同配对)。查看每个配对中发生的A数。

  SELECT
    Code,
    COUNT(SubCode) as SubCodeCount
    SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END)
      as SubCodeCountWithA
  FROM
    --previous
  GROUP BY Code

按代码重新组合这些配对(现在每行都是一个代码)并计算有多少个子代码,以及有多少个子代码有一个A.

SELECT Code
FROM
  --previous
WHERE SubCodeCountWithA = SubCodeCount

使用与A的子代码具有相同数量的子码来发出这些代码。

答案 2 :(得分:0)

在您的选择中,添加一个where子句,内容为:

Select [stuff]
From Table T
Where Exists
    (Select * From Table 
     Where Code = T.Code
        And Status = 'A')
  And Not Exists
    (Select * From Table I
     Where Code = T.Code 
       And Not Exists
          (Select * From Table
           Where Code = I.Code
               And SubCode = I.SubCode
               And Status = 'A'))

英文 告诉我行, 至少有一行状态为“A”的行, 并且没有任何特定子代码的行, 没有至少一行代码/子代码,状态为“A”

答案 3 :(得分:-1)

INSERT theTempTable (Code)
SELECT t.Code
FROM   theTable t
       LEFT OUTER JOIN theTable subT ON (t.Code = subT.Code AND subT.status <> 'A')
WHERE  subT.Code IS NULL
GROUP BY t.Code

这应该可以解决问题。逻辑有点棘手,但我会尽力解释它是如何派生出来的。

外部联接与IS NULL检查相结合,允许您搜索条件的缺席。将其与您正常查找的内容相反(在本例中为status ='A'),当没有与不匹配的行时查询成功。这与((没有行)OR(所有行匹配)相同。由于我们知道由于表上的其他查询而存在行,因此所有行都必须匹配。