У меня есть 2 таблицы данных о продажах, у которых нет общих ключей, только дата продажи и имя клиента. Я хочу присоединиться к ним так, чтобы для каждой строки из таблицы A было не более 1 совпадения из таблицы B или 0, если ничего не найдено. Проблема в том, что один и тот же клиент появляется дважды в один и тот же день. Итак, если у меня есть такие данные
Table A Table B
Customer | Date | Receipt Customer | Date | Invoice
=============================== ===============================
John | 2018-01-01 | A John | 2018-01-01 | C
John | 2018-01-01 | B John | 2018-01-01 | D
Как мне это получить
Result
Customer | Date | Receipt | Invoice
=========================================
John | 2018-01-01 | A | C
John | 2018-01-01 | B | D
Не имеет значения, совпадает ли квитанция A со счетом-фактурой C или D, если каждая из них сопряжена один раз. В настоящее время мой запрос объединяет все из них, AC, AD, BC, BD
Обновлено: чтобы уточнить, у меня не может быть дубликатов из любой таблицы. Один счет и квитанция могут появиться только один раз. Итак, приемлем любой из этих результатов:
У вашей проблемы может быть решение, но оно будет грязным и ненадежным, независимо от того, как вы это делаете (что, если два человека с одним и тем же именем заказывают что-то в один и тот же день?). Сначала вам нужно иметь правильную структуру, а правильная структура (= схема) включает первичные ключи, чтобы иметь возможность создавать внешние ключи при использовании индекса.
Я понимаю это, но я объединяю данные из двух отдельных систем (обе не мои, я не могу их изменить), поэтому мне нужен способ сделать это. Да, и в любом случае имена клиентов обычно являются длинными названиями компаний, поэтому вероятность дублирования имени меньше.
«Мне нужен способ сделать это» - крик далеко из «Мне нужен способ сделать это в SQL». Пожалуйста, посмотрите мой ответ - такие вещи действительно действительно нужно делать на уровне отображения, а не в результате, возвращаемом SQL.






Это неприятно, потому что вам нужно перечислить две таблицы, а затем либо join, либо агрегировать. Вот один из способов:
select customer, date, max(receipt) as receipt, max(invoice) as invoice
from ((select a.customer, a.date, a.receipt,
(@rnr := if (@cd = concat_ws(';', customer, date), @rnr + 1,
if (@cd := concat_ws(';', customer, date), 1, 1)
)
) as seqnum
from a cross join
(select @rnr := 0, @cd := '') params
order by a.customer, a.date
) union all
(select b.customer, b.date, b.invoice,
(@rni := if (@cd = concat_ws(';', customer, date), @rni + 1,
if (@cd := concat_ws(';', customer, date), 1, 1)
)
) as seqnum
from b cross join
(select @rni := 0, @cd := '') params
order by a.customer, a.date
)
) cd
group by customer, date, seqnum;
Не голосование против, но я вздрогнул, когда увидел этот код. Я могу просто представить себе, как выглядит лицо разработчика, который наследует это и должен выполнять обслуживание / расширение хранимой процедуры, которая ее использует ...
Почему бы просто не сделать отдельные после того, как вы соединили две таблицы, если вам нужны только отдельные записи?
SELECT DISTINCT a.Customer,
a.Date,
a.Receipt,
b.Invoice
FROM Table_A a
JOIN Table_B b
ON a.Customer = b.Customer
AND a.Date = b.Date
Поскольку тогда будут дубликаты, например AD и BD, sql видит их как отдельные.
Я дам ответ, который вам, вероятно, не понравится: этого нельзя делать в SQL. Это проблема презентации / отображения.
Выполняйте такую работу на уровне, который отображает данные для пользователя, а не в серверной части SQL. Ищут ли они это на веб-странице? Затем попросите веб-страницу получить необработанные данные и отформатировать их по мере необходимости - пусть она помещает содержимое ежедневных квитанций или счетов-фактур каждого дня в отдельные блоки div. SQL отправляет электронное письмо с этими данными? Тогда не заставляйте его генерировать обычное текстовое электронное письмо - пусть он сгенерирует HTML и поместит данные в ячейки таблицы (чтобы вам не приходилось координировать строки между двумя наборами данных с возможно разными объемами данных).
Вы действительно не хотите играть в игру, пытаясь сделать вывод SQL красивым изнутри SQL. Потому что, честно говоря, код в принятом вами ответе может быть Работа правильно, но мне не хотелось бы пытаться поддерживать его на протяжении многих лет ...
Нет, это не проблема с презентацией / отображением, потому что это вставит данные в мою таблицу. Это извлекает данные из двух сторонних баз данных для вставки в мою, так что это проблема с данными.
... нет, это не так. Нет причин, по которым вы не можете извлечь эти данные и сохранить их в правильной, нормализованной манере в своей базе данных (если это не имеет смысла, вы можете поискать в Google `` Нормализация SQL '' и получить много полезной информации о том, что Я говорю о.) И если никому не нужно видеть данных в этом формате, определенно нет веских причин для хранить это таким образом.
О да, есть, я ничего не могу сделать с их базами данных, я не контролирую сторонние системы. Я могу только обработать вывод. Моя база данных нормализована, их нет
Вам нужен способ однозначной идентификации строк в каждой из данных таблиц.