Преобразование данных в SQL: удаление информации об учетной записи из набора данных на основе значения в столбце - PullRequest
0 голосов
/ 06 апреля 2020

Я ищу схожий оператор SQL с оператором any в R . У меня есть набор данных временных рядов, который начинается в 2014 году и заканчивается в 2020 году. У меня есть столбец, в котором указывается, добровольно или невольно люди меняли препарат в 2016 году. Что я хочу сделать, так это полностью удалить всех людей, которые невольно меняли наркотик. В R то, что я хотел бы сделать, это сгруппировать по идентификатору индивидуума и удалить все идентификаторы из набора данных, если столбец DrugChange имеет значение «Непроизвольно». Мой код R выглядел бы так:

df<-df%>%group_by(ID)%>%filter(!any(DrugChange=='Involuntarily'))

В SQL Я искал несколько простое решение, и (глупо) думал, что просто использование оператора WHERE будет работать, но все он делает это удалить одну строку, а не все строки. Есть ли способ, которым я могу использовать оператор WHERE или есть лучший метод?

Ответы [ 2 ]

2 голосов
/ 06 апреля 2020

Я думаю, вы хотите что-то вроде этого:

select id
from t
group by id
having sum(case when DrugChange = 'Involuntarily' then 1 else 0 end) = 0;
1 голос
/ 06 апреля 2020

Насколько я понимаю, вы хотите взять подмножество строк таким образом, чтобы, если какая-либо строка для идентификатора имела Involuntarily в столбце DrugChange, все строки для этого идентификатора должны быть исключены, как в примере в примечании. в конце все строки для идентификатора 1 будут исключены, а все строки для идентификатора 2 будут сохранены.

1) оконная функция Использование тестовых данных в примечании в конце и SQL оконная функция создает столбец ok, который равен 1 для каждой строки идентификатора, не имеющего Involutarily в столбце DrugChange, а затем выбирает только эти строки. Мы удалили столбец ok, но если вы хотите, опустите [-1].

library(sqldf)

sqldf("select * from (
  select not max(DrugChange = 'Involuntarily') over (partition by ID) ok, * 
  from df
 ) where ok")[-1]

, что дает:

  DrugChange ID
1          X  2
2          X  2

1a) Это может быть записано в терминах CTE, например:

sqldf("with inner as (
  select not max(DrugChange = 'Involuntarily') over (partition by ID) ok, *
  from df
) 
select * from inner where ok")[-1]

2) join Альтернативный подход заключается в создании одной строки для каждого идентификатора со значением ok и затем присоединении к df если все в порядке 1.

sqldf("select a.* 
  from df a join (select ID, not max(DrugChange = 'Involuntarily') ok 
                  from df 
                  group by ID) b on a.ID = b.ID and b.ok")

, что дает:

  DrugChange ID
1          X  2
2          X  2

2a) Мы также можем написать это в терминах CTE:

sqldf("with right as (
  select ID, not max(DrugChange = 'Involuntarily') ok 
  from df 
  group by ID
)
select a.* from df a join right b on a.ID = b.ID and b.ok")

3) в Другой подход заключается в использовании in, как показано здесь:

sqldf("select *
  from df
  where id not in (select distinct id from df where DrugChange = 'Involuntarily')")

, давая:

  DrugChange ID
1          X  2
2          X  2

Это также будет работать без ключевого слова distinct.

3a) Мы также можем написать его с помощью CTE:

sqldf("with ids as (
    select distinct id from df where DrugChange = 'Involuntarily'
  )
  select * from df where id not in ids")

Примечание

Test использованные данные.

df <- data.frame(DrugChange = c("Involuntarily", "X", "X", "X"), ID = c(1,1,2,2))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...