#mysql #sql #join #left-join
#mysql #sql #Присоединиться #левое соединение
Вопрос:
Хорошо, с помощью SO и некоторых моих собственных, по общему признанию, ограниченных умственных способностей, я получил свой запрос в основном работающим. Я получаю результат, который мне нужен, LEFT JOIN
и он отображается во внешнем запросе. Тем не менее, он отображается несколько раз для каждой строки с тем же идентификатором, что и ожидалось, но это не то, что мне нужно…
Мне интересно, возможно ли показать объединенный результат только один раз.Я нашел много ответов в Интернете только для извлечения первой строки из таблицы, которая была оставлена присоединенной. Однако то, что я ищу, — это показать объединенный результат только один раз в результате (не обязательно в первый раз).
Это [упрощенная версия] моего запроса:
select
`order`.order_id,
`order`.total,
`order`.comment,
`order`.shipping_cost,
`ct`.amount as credit
from `order`
left join (
select
customer_id,
sum(amount) as amount
from `customer_transaction`
where
amount > 0
and integrated = 0
group by
customer_id
) as ct
on `ct`.`customer_id` = `order`.`customer_id`
where
`order`.integrated = 0;
Предполагается, что это позволяет получить еще не интегрированную информацию о заказе, включая кредит клиента. К сожалению, кредит хранится в виде строк в ct
таблице, не связанных с определенным заказом, что имеет смысл, но программное обеспечение, которое интегрирует это, хочет, чтобы это число было в заказе.
Приведенный выше запрос «работает», пока у одного клиента не будет более одного заказа. В этом случае, если я использую приведенный выше запрос, он будет эффективно считать, что ко всем заказам применен кредит. Например, приведенный выше запрос возвращает результат, подобный:
------------- ---------- ----------- --------- --------------- --------
| customer_id | order_id | total | comment | shipping_cost | credit |
------------- ---------- ----------- --------- --------------- --------
| 52227 | 184589 | 28.6910 | | 12.7410 | 8.0000 |
| 52227 | 184590 | 28.6910 | | 12.7410 | 8.0000 |
------------- ---------- ----------- --------- --------------- --------
У этого клиента есть кредит в размере 8 долларов США «на своем счете», а не 16 долларов США. Т.Е. Сумма неиспользованных кредитных транзакций для клиента составляет 8. Я пытаюсь получить этот кредит, чтобы он отображался только один раз. Другими словами, это результат, который я хотел бы:
------------- ---------- ----------- --------- --------------- --------
| customer_id | order_id | total | comment | shipping_cost | credit |
------------- ---------- ----------- --------- --------------- --------
| 52227 | 184589 | 28.6910 | | 12.7410 | 8.0000 |
| 52227 | 184590 | 28.6910 | | 12.7410 | NULL |
------------- ---------- ----------- --------- --------------- --------
(Обратите внимание на значение NULL в правом нижнем углу. Это также может быть 0 или, может быть, даже 8 / $ NUM_ROWS. Мне нужно было бы проверить, будет ли программное обеспечение работать с этим. Вероятно, нет.)
Причина этого сумасшествия в том, что одна часть программного обеспечения хранит кредит как одну или несколько строк, связанных с клиентом, а другая ожидает его как часть одного заказа, и предполагается, что все они будут интегрированы «сразу». Он запускает один запрос, чтобы получить всю информацию о заказе, включая кредит, и второй для позиций (без кредита). Итак … мне нужно внести кредит в заказ, затем установить для него значение integrated = 1, чтобы он не использовался в следующий раз (у меня уже есть эта часть, работающая).
Есть идеи, как я могу отобразить кредит только один раз, или это невозможно с помощью «простого» запроса (в отличие от кода)?
Спасибо
Комментарии:
1. Создайте SQL-скрипку с вашими тестовыми данными и опубликуйте ожидаемый результат.
Ответ №1:
Вы можете сделать это, используя левое соединение. Идея состоит в том, чтобы иметь порядковый номер в первой таблице left join
:
select o.order_id, o.total, o.comment, o.shipping_cost, ct.amount as credit
from (select o.*,
@rn := if(@cid = customer_id, @rn 1, 1) as rn,
@cid := customer_id
from `order` o cross join
(select @rn := 0, @cid := 0) vars
) o left join
(select customer_id, sum(amount) as amount
from `customer_transaction`
where amount > 0 and integrated = 0
group by customer_id
) ct
on `ct`.`customer_id` = o.`customer_id` and o.rn = 1
where o.integrated = 0;
A left join
сохраняет все строки в первой таблице и соответствующие строки во второй таблице, если это необходимо. Поскольку условие o.rn = 1
соответствует только первой строке, значения будут получены только в первой строке.