Как создать новый двоичный столбец, проверяя все строки темы? - PullRequest
1 голос
/ 07 марта 2020

У меня есть таблица, как показано ниже

subject_id  Desc  Name   class   BC  FU  PA  VI 
1                Fung     FU      0   1   0  0  
1                Para     PA      0   0   1  0  
1                Viru     VI      0   0   0  1  
1                Para     PA      0   0   1  0  
1             T5 Bacte    BC      1   0   0  0  
1             T6 Bacte    BC      1   0   0  0 
2             T5 Bacte    BC      1   0   0  0
2                Fung     FU      1   0   0  0

Что я хотел бы сделать, это создать новый столбец "BC_FU", который будет иметь 1, если у субъекта есть 1 в столбце B C и Колонна ФУ. Но его следует искать не в одной строке, а во всех записях одного и того же субъекта.

Те же логики c применимы и к столбцу BC_VI (еще один новый столбец)

Например: если вы посмотрите на subject_id = 1, мы можем видеть, что у него есть 1 в столбце B C в строках 5 и 6, тогда как у него FU = 1 в строке 1. Теперь мы знаем, что subject_id имеет оба B C и ФУ в этих записях (из базы данных)

Это то, что я пытался, но не помогает. Я пытаюсь написать в BigQuery, так что ваша помощь по исправлению или исправлению этого в BigQuery будет полезна

select *, 
CASE WHEN (MAX(BC) == 1 AND MAX(FU) == 1) THEN 1
ELSE 0 END AS BC_FU,
CASE WHEN (MAX(BC) == 1 AND MAX(VI) == 1) THEN 1
ELSE 0 END AS BC_VI,
FROM TABLE T
GROUP BY SUBJECT_ID

Итак, я хотел бы создать вывод, который выглядит следующим образом

subject_id  Desc  Name  class  BC FU PA VI BC_FU BC_VI
1                 Fungi  FU     0  1  0 0   1     1
1                 Para   PA     0  0  1 0   1     1
1                 Virus  VI     0  0  0 1   1     1 
1                 Para   PA     0  0  1 0   1     1 
1             T5  Bacte  BC     1  0  0 0   1     1
1             T6  Bacte  BC     1  0  0 0   1     1
2             T5  Bacte  BC     1  0  0 0   1     1
2                 Virus  VI     0  1  0 1   1     1

Ответы [ 4 ]

2 голосов
/ 07 марта 2020

Вы можете сделать следующее

select t1.*
       ,max(BC) over(partition by subject_id)
        *max(FU) over(partition by subject_id) as BC_FU
       ,max(BC) over(partition by subject_id)
        *max(VI) over(partition by subject_id) as BC_VI
  from your_table t1
1 голос
/ 07 марта 2020

Я прочитал ваш вопрос и позвольте мне также добавить свое решение.

SELECT  t1.*,
        CASE WHEN (MAX(BC) OVER (PARTITION BY subject_id) +
                 MAX(FU) OVER (PARTITION BY subject_id) ) == 2
             THEN 1
             ELSE 0
             END AS BC_FU
        CASE WHEN (MAX(BC) OVER(PARTITION BY subject_id) +
                  MAX(VI) OVER(PARTITION BY subject_id) ) == 2
             THEN 1
             ELSE 0
             END AS BC_VI
FROM    table as t1
ORDER BY subject_id

Вот несколько советов, которые, как мне показалось, могут быть полезны для вас:)

  • OVER () иногда называется оконной функцией. Если вы наберете SELECT (aggregating function) OVER(PARTITION BY columnA), вы можете использовать функцию агрегирования, но не превращать результат в одну строку одновременно. (Пожалуйста, игнорируйте это, если вы уже знаете)

  • Как уже упоминал г-н Тим, хорошо удалить ненужный подзапрос (запрос внутри другого), чтобы повысить удобочитаемость.

  • Обязательно добавляйте 'Else 0' в каждое предложение CASE, чтобы не вызвать возможность появления 'NULL'.

Здесь я решил суммировать максимальное значение B C и FU, чтобы проверить, равно ли оно 2, или нет, вместо того, чтобы не проверять «пересечение» (например, max (B *) 1025 *) == 1 AND max (FU) == 1) как и сообщение Mr.Tim. Это потому, что я подумал, что вы, вероятно, добавите в будущем такой столбец, как «BC_FU_VI», когда '2' увеличит читабельность, то это предложение в случае попытки фактически преобразовать два столбца в один столбец.

Спасибо.

1 голос
/ 07 марта 2020

Если я правильно понимаю ваше требование, вы просто сможете использовать функции analyti c здесь:

SELECT *,
    CASE WHEN MAX(BC) OVER (PARTITION BY subject_id) +
              MAX(FU) OVER (PARTITION BY subject_id) = 2 THEN 1 ELSE 0 END AS BC_FU,
    CASE WHEN MAX(BC) OVER (PARTITION BY subject_id) +
              MAX(VI) OVER (PARTITION BY subject_id) = 2 THEN 1 ELSE 0 END AS BC_VI
FROM yourTable
ORDER BY subject_id;

Этот ответ избавляет от необходимости ненужного подзапроса.

1 голос
/ 07 марта 2020
select t1.*, tmp.BC_FU, tmp.BC_VI
from your_table t1
join
(
  select subject_id, 
         CASE WHEN MAX(BC) + MAX(FU) = 2 THEN 1 ELSE 0 END AS BC_FU,
         CASE WHEN MAX(BC) + MAX(VI) = 2 THEN 1 ELSE 0 END AS BC_VI
  from your_table
  group by subject_id
) tmp on t1.subject_id = tmp.subject_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...