группировка записей в одну временную таблицу - PullRequest
0 голосов
/ 30 декабря 2008

У меня есть таблица, в которой один столбец содержит повторяющиеся записи, но другие столбцы различны. ну как то так

Статус версии подкода кода

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 п.н. 1 А

5678 BJ 1 A

0987 ЧЧ 1 А

Так в приведенной выше таблице. субкод и версия являются уникальными значениями, тогда как код повторяется. Я хочу перенести записи из вышеуказанной таблицы во временную таблицу. Только записи, которые я хотел бы передать, - это где ВСЕ подкоды для кода имеют статус «А», и я хочу, чтобы они были во временной таблице только один раз.

Так из примера выше. временная таблица должна иметь только 5678 и 0987, поскольку все подкоды, относящиеся к 5678, имеют статус «A», а все подкоды для 0987 (он имеет только один) имеют статус A. 1234 опущен, поскольку его подкод «DB» имеет статус «P»

Буду признателен за любую помощь!

Ответы [ 4 ]

1 голос
/ 30 декабря 2008

Вот мое решение

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

Сгруппируйте коды и подкоды (каждая строка представляет собой отдельное сочетание кода и подкода). Посмотрите, сколько А произошло в каждой паре.

  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

Испускать эти коды с тем же числом подкодов, что и подкодов с буквой А.

1 голос
/ 30 декабря 2008

Немного неясно, вступит ли в игру колонка версий. Например, хотите ли вы рассматривать только строки с самой большой версией или если ЛЮБОЙ подкадр имеет «А», если он считается. Возьмите 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'
            )
    )
0 голосов
/ 30 декабря 2008
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'), и запрос завершится успешно, если нет строк, которые не соответствуют . Это то же самое, что и ((нет строк) ИЛИ (все строки совпадают)). Поскольку мы знаем, что есть строки из-за другого запроса в таблице, все строки должны совпадать.

0 голосов
/ 30 декабря 2008

В ваш выбор добавьте предложение 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»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...