Группировка записей в одну временную таблицу

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

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

1234 D1 1 А

1234 D1 0 P

1234 DA 1 А

1234 ДБ 1-пол.

5678 BB 1 А

5678 BB 0 P

5678 БП 1 А

5678 BJ 1 А

0987 HH 1 А

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

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

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

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
0
208
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Это не дает правильных результатов. 5678 будет исключен, поскольку существует по крайней мере одна строка со статусом, отличным от «A». (также в вашем запросе есть SubCode, где, я думаю, вы имели в виду статус)

Tom H 30.12.2008 18:52

Теперь это работает ... у меня был "<>" вместо " = "

Charles Bretana 30.12.2008 23:12
Ответ принят как подходящий
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'), и запрос будет успешным, когда нет строк, которые не совпадают. Это то же самое, что ((нет строк) ИЛИ (все строки совпадают)). Поскольку мы знаем, что есть строки из-за другого запроса в таблице, все строки должны совпадать.

Это не дает правильных результатов. 5678 будет исключен, поскольку существует по крайней мере одна строка со статусом, отличным от «A».

Tom H 30.12.2008 18:53

Немного неясно, входит ли в игру столбец версии. Например, вы хотите рассматривать только строки с самой большой версией или если ЛЮБОЙ вложенный код имеет "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'
            )
    )

Хорошее решение. FROM - враг производительности, но вы это знаете.

Amy B 30.12.2008 20:10

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

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

Испускайте те коды, которые имеют такое же количество субкодов, что и субкоды с A.

Тоже интересное решение. В ограниченном наборе данных выше в таблице без индексов я вижу высокую стоимость сортировки (относительно), но с реальной таблицей с данными это может быть лучше, чем сканирование таблицы из моего метода.

Tom H 30.12.2008 22:06

Другие вопросы по теме