SQL соединение многие ко многим, что исключает несовпадение строк при наличии совпадения - PullRequest
0 голосов
/ 20 марта 2020

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

Например:

enter image description here

Таблица A:

+-----+----------------+---------------+
| key |      qhr       | observation_A |
+-----+----------------+---------------+
|   1 | 1/1/2020 10:00 | A             |
|   1 | 1/1/2020 10:00 | B             |
|   1 | 1/1/2020 10:15 | A             |
|   1 | 1/1/2020 10:15 | B             |
|   1 | 1/1/2020 10:30 | B             |
|   1 | 1/1/2020 10:45 | A             |
|   1 | 1/1/2020 11:00 | B             |
|   1 | 1/1/2020 11:00 | C             |
|   1 | 1/1/2020 11:15 | C             |
|   2 | 1/1/2020 10:00 | C             |
|   2 | 1/1/2020 10:00 | B             |
|   2 | 1/1/2020 10:15 | A             |
|   2 | 1/1/2020 10:15 | C             |
|   2 | 1/1/2020 10:30 | A             |
|   2 | 1/1/2020 10:45 | C             |
|   2 | 1/1/2020 11:00 | A             |
|   2 | 1/1/2020 11:00 | C             |
|   2 | 1/1/2020 11:15 | B             |
+-----+----------------+---------------+

Таблица B:

+-----+----------------+---------------+
| key |      qhr       | observation_B |
+-----+----------------+---------------+
|   1 | 1/1/2020 10:00 | A             |
|   1 | 1/1/2020 10:00 | B             |
|   1 | 1/1/2020 10:15 | A             |
|   1 | 1/1/2020 10:15 | C             |
|   1 | 1/1/2020 10:30 | B             |
|   1 | 1/1/2020 10:45 | A             |
|   1 | 1/1/2020 11:00 | A             |
|   1 | 1/1/2020 11:00 | C             |
|   1 | 1/1/2020 11:15 | C             |
|   2 | 1/1/2020 10:00 | C             |
|   2 | 1/1/2020 10:00 | B             |
|   2 | 1/1/2020 10:15 | A             |
|   2 | 1/1/2020 10:15 | C             |
|   2 | 1/1/2020 10:30 | B             |
|   2 | 1/1/2020 10:45 | C             |
|   2 | 1/1/2020 11:00 | A             |
|   2 | 1/1/2020 11:15 | A             |
+-----+----------------+---------------+

Ожидаемый результат:

+-----+----------------+---------------+---------------+-------+
| key |      qhr       | observation_A | observation_B | MATCH |
+-----+----------------+---------------+---------------+-------+
|   1 | 1/1/2020 10:00 | A             | A             | Y     |
|   1 | 1/1/2020 10:00 | B             | B             | Y     |
|   1 | 1/1/2020 10:15 | A             | A             | Y     |
|   1 | 1/1/2020 10:15 | B             | C             | N     |
|   1 | 1/1/2020 10:30 | B             | B             | Y     |
|   1 | 1/1/2020 10:45 | A             | A             | Y     |
|   1 | 1/1/2020 11:00 | B             | A             | N     |
|   1 | 1/1/2020 11:00 | C             | C             | Y     |
|   1 | 1/1/2020 11:15 | C             | C             | Y     |
|   2 | 1/1/2020 10:00 | C             | C             | Y     |
|   2 | 1/1/2020 10:00 | B             | B             | Y     |
|   2 | 1/1/2020 10:15 | A             | A             | Y     |
|   2 | 1/1/2020 10:15 | C             | C             | Y     |
|   2 | 1/1/2020 10:30 | A             | B             | N     |
|   2 | 1/1/2020 10:45 | C             | C             | Y     |
|   2 | 1/1/2020 11:00 | A             | A             | Y     |
|   2 | 1/1/2020 11:00 | C             |               | N     |
|   2 | 1/1/2020 11:15 | B             | A             | N     |
+-----+----------------+---------------+---------------+-------+

Я пытался использовать полное внешнее объединение (объединение по ключу и qhr), чтобы включить моменты, когда наблюдения не совпадают, но когда я это делаю, я получаю каждый потенциал комбинации даже если есть совпадение, подобное:

+-----+----------------+---------------+---------------+-------+
| key |      qhr       | observation_A | observation_B | MATCH |
+-----+----------------+---------------+---------------+-------+
|   1 | 1/1/2020 10:00 | A             | B             | N     |
|   1 | 1/1/2020 10:00 | A             | A             | Y     |
|   1 | 1/1/2020 10:00 | B             | B             | Y     |
|   1 | 1/1/2020 10:00 | B             | A             | N     |
+-----+----------------+---------------+---------------+-------+

Я пытаюсь найти способ включить любые допустимые несоответствия, но исключаю строки 1 и 4, поскольку A и B фактически совпали.

Я работаю в spark, поэтому я могу использовать spark SQL или фреймы данных pyspark для решения этой проблемы и даже потенциально pandas. Любой совет будет оценен.

1 Ответ

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

Я не совсем понял, что вы хотите, чтобы мы использовали в качестве t ie -точек при объединении двух фреймов данных. Надеюсь, я прочитал это хорошо. Я привязал ключ и QHR. Кричите, если не правильно. Вы получите помощь. Мои шаги; Приведите дату в datetime, извлеките минуты и преобразуйте их обратно в тип объекта

df4['qhrminute']=pd.to_datetime(df4['qhr']).dt.minute.astype('object')
df1['qhrminute']=pd.to_datetime(df1['qhr']).dt.minute.astype('object')

Выполните внешнее соединение для столбцов key и qhrminute. Внешнее объединение сохраняет все значения из всех атрибутов присоединяемых информационных фреймов по сравнению с внутренним, слева и т. Д. c

merged_df = df4.merge (df1, how = 'external', on = ['key', 'qhrminute' ], суффиксы = ('_A', '_B'))

Проверка и условие атрибута с помощью np.where

merged_df['Match']= np.where(merged_df['obs_A'] == merged_df['obs_B'], 'Y', 'N')

удаление необязательных столбцов

merged_df.drop(columns=['qhr_A','qhrminute'], inplace=True)
merged_df.rename({'qhr_B':'qhr'}, axis=1, inplace=True)
merged_df

Объединение строки в obs_A и obs_B, сортируйте их по алфавиту и удаляйте дубликаты в объединенном отсортированном столбце и qhr.

  merged_df["com"] = merged_df["obs_A"] + merged_df["obs_B"]
   merged_df['com1'] = merged_df['com'].apply(lambda x: ' '.join(sorted(x.split()))).sort_values( ascending=True)
merged_df.drop_duplicates(['qhr','com1'],keep= 'last')
...