Как покинуть объединение на основании указанных c условий в Python SQL? - PullRequest
0 голосов
/ 18 марта 2020

У меня есть 2 кадра данных, df1 и df2, например:

df1 =

person_id 
10001
...
10900

df2 =

person_id month_1 place_1
10001       255     X
... 
10900       2111    Y
10900       500     X
10900       200     X

Я хочу уйти присоединяйтесь к df2 только в df1, где place_1 is X и конечное значение как sum(month_1) Примерно так:

newdf =

person_id month_1 place_1
10900       700      X

До сих пор я думал о создании своего кода sqlite3 следующим образом:

import sqlite3
conn=sqlite3.connect(':memory:') 
crsr=conn.cursor()

qry='''
SELECT df1.*
FROM df1
left join df2 on sum(month_1)
WHERE UPPER(place_1) like '%X%'
group by df2.person_id
on df1.person_id = df2.person_id;
''' 

new_df=pd.read_sql(qry,conn)

Что не так в моем подходе к запросу? Как правильно реализовать логику запросов c?

Я учусь использовать SQL для управления моими данными в Python. Любая помощь будет очень полезна!

Ответы [ 4 ]

0 голосов
/ 18 марта 2020

Я предполагаю, что вам нужны все строки df1, и поэтому вы используете соединение LEFT. Таким образом, условие UPPER(df2.place_1) LIKE '%X%' должно быть установлено в предложении ON, а не в предложении WHERE:

SELECT df1.person_id, SUM(month_1) AS month_1, MAX(place_1) place_1
FROM df1 LEFT JOIN df2 
ON df1.person_id = df2.person_id AND UPPER(df2.place_1) LIKE '%X%'
GROUP BY df1.person_id;

Если вместо NULL s вы хотите 0 s в результатах для несоответствующие строки затем изменяются SUM(month_1) на:

COALESCE(SUM(month_1), 0)

См. demo . Результаты:

| person_id | month_1 | place_1 |
| --------- | ------- | ------- |
| 10001     | 255     | X       |
| 10900     | 700     | X       |
0 голосов
/ 18 марта 2020

Это ваша ошибка:

left join df2 on sum(month_1)

ON должно выполняться условие для объединения строк. sum(month_1) - это не условие, а отдельное значение.

И хотя, скажем, sum(month_1) > 0 - это условие, оно также не будет работать, поскольку вы объединяете отдельные строки, а sum(month_1) - это не значение строки, но агрегация по нескольким строкам.

У вас on df1.person_id = df2.person_id позже, но предложение ON относится к JOIN, а не к концу запроса.

Вам нужно выбрать SUM(df2.month_1), поэтому поместите его в предложение SELECT. Следующий запрос дает вам все df1 строк вместе с их month_1 суммой (или нулем, когда для человека нет df2 записей).

SELECT df1.*, SUM(df2.month_1)
FROM df1
left join df2 ON df2.person_id  = df1.person_id
WHERE UPPER(df1.place_1) = 'X'
GROUP BY df1.person_id;

Я не знаю, является ли SQLite поддерживает группирование по ключу и выбор его функционально зависимых столбцов (df1.*). Если вы хотите показать только df1.person_id, вам следует заменить df1.* на df1.person_id. Если вам нужно больше df1 столбцов, а SQLIte не позволяет df1.*, то вы можете объединиться перед объединением (что я считаю хорошим стилем в любом случае):

SELECT df1.*, d2.total
FROM df1
left join 
(
  SELECT person_id, SUM(month_1) AS total
  FROM df2
  GROUP BY person_id
) d2 ON d2.person_id  = df1.person_id 
WHERE UPPER(df1.place_1) = 'X';
0 голосов
/ 18 марта 2020

Попробуйте ниже, это не объединяет данные, просто фильтрует по месту и идентификаторам в df1:

select person_id, sum(month_1) from df2
where place_1 = 'X' and
      exists(select 1 from df1
             where person_id = df2.person_id)
group by person_id

или используя in:

select person_id, sum(month_1) from df2
where place_1 = 'X' and
      person_id in (select person_id from df1)
group by person_id
0 голосов
/ 18 марта 2020

Если я правильно понял ваш вопрос, вы ищете все записи в df2 с таким местом, как X, и если у этого человека есть какие-то записи в df1, потяните и их.

Чтобы сделать это следующее даст вам набор записей. (При агрегировании не сгруппированных столбцов должна использоваться функция агрегирования, такая как MAX или MIN et c)

   SELECT df2.person_id
         ,sum(df2.month_1)
         ,max(df1.person_name) 
     FROM df2
LEFT JOIN df1 
       ON df2.person_id=df1.person_id
    WHERE UPPER(df2.place_1) like '%X%'
 GROUP BY df2.person_id
...