#sql #oracle
Вопрос:
Я создаю таблицу, используя несколько внутренних запросов на объединение в других таблицах, и один из моих запросов возвращает несколько совпадений (правильно в зависимости от того, как работает эта функция), но мне действительно просто нужно вернуть одно совпадение, первое, которое оно попадет в сравнение, подойдет. Ниже приведен мой код. В последнем запросе ВНУТРЕННЕГО СОЕДИНЕНИЯ может быть несколько совпадений.transaction_id = e.pb_trans_id в таблице repldoadm.vw_ire_trade_transactions e. Могу ли я указать, чтобы просто вернуть 1 совпадение?
»’
SELECT
distinct a.transaction_id,
b.currency_id,
h.SIG_CURRENCY_CODE,
b.charge_id,
c.charge_type_id,
d.charge_group,
e.account_name,
f.sig_entity_label,
e.trading_userid,
e.exchange_id,
e.tradeable_instr_name,
g.underlying_sym_bloomberg,
g.fut_expiration_date,
e.trade_date,
timestamp_table.timeformated,
a.rate * a.basis_value AS dma_fee,
SUM(A.RATE * A.BASIS_VALUE) OVER () as DMA_FEE_TOTAL
FROM
repldoadm.ire_estimate_trans_map a
LEFT JOIN repldoadm.ire_charges_estimate b ON a.estimate_id = b.estimate_id
LEFT JOIN repldoadm.ire_charges_lu c ON b.charge_id = c.charge_id
LEFT JOIN repldoadm.ire_charge_types_lu d ON c.charge_type_id = d.charge_type_id
LEFT JOIN repldoadm.vw_ire_trade_transactions e ON a.transaction_id = e.pb_trans_id --or a.transaction_id = e.PB_TRANS_ID
LEFT JOIN (
SELECT
to_char(create_ts, 'HH24:MI:SS') AS timeformated,
trans_id,
pb_trans_id
FROM
repldoadm.vw_ire_trade_transactions
) timestamp_table ON ( a.transaction_id = timestamp_table.trans_id or a.transaction_id = timestamp_table.pb_trans_id)
LEFT JOIN repldoadm.vw_ire_accounts f ON e.account_name = f.pb_account_name
LEFT JOIN stig_adm.instrument_universe g ON e.tradeable_instr_name = g.short_name
LEFT JOIN STIG_ADM.BBG_LU_CURRENCY h ON c.payment_currency_id = h.SIG_CURRENCY_ID
»’
Комментарии:
1. «…но мне действительно просто нужно отодвинуть одну спичку…» — Как вы решаете, какую из них выбрать? Просто случайный, с наибольшей ценностью чего-то и т. Д…
2.
INNER JOIN
В вашем запросе нет, поэтому ваш вопрос не имеет смысла.3. @TheImpaler да, случайность-это нормально
4. @GordonLinoff я имел в виду левое присоединение
Ответ №1:
Для этого вы можете использовать боковое соединение с предельным предложением. Для бокового внешнего соединения я предлагаю использовать OUTER APPLY
, потому что, в отличие от с LEFT JOIN LATERAL
, вам не нужно добавлять фиктивное ON
предложение, чтобы сделать это синтаксически правильным.
SELECT
distinct a.transaction_id,
b.currency_id,
h.SIG_CURRENCY_CODE,
b.charge_id,
c.charge_type_id,
d.charge_group,
e.account_name,
f.sig_entity_label,
e.trading_userid,
e.exchange_id,
e.tradeable_instr_name,
to_char(e.create_ts, 'HH24:MI:SS'),
g.underlying_sym_bloomberg,
g.fut_expiration_date,
e.trade_date,
-- timestamp_table.timeformated,
a.rate * a.basis_value AS dma_fee,
SUM(A.RATE * A.BASIS_VALUE) OVER () as DMA_FEE_TOTAL
FROM
repldoadm.ire_estimate_trans_map a
LEFT JOIN repldoadm.ire_charges_estimate b ON a.estimate_id = b.estimate_id
LEFT JOIN repldoadm.ire_charges_lu c ON b.charge_id = c.charge_id
LEFT JOIN repldoadm.ire_charge_types_lu d ON c.charge_type_id = d.charge_type_id
OUTER APPLY
(
SELECT *
FROM repldoadm.vw_ire_trade_transactions tt
WHERE tt.pb_trans_id = a.transaction_id
FETCH FIRST ROW ONLY
) e;
Ответ №2:
Если вам все равно, какую строку возвращать, возможно, ROW_NUMBER
вам поможет аналитическая функция. Ваш текущий запрос — с добавлением именованной функции — будет использоваться в качестве подзапроса (или CTE, как в моем примере), в то время как «окончательный» запрос вернет строки, которые RN = 1
.
Что-то вроде этого:
WITH temp AS
( SELECT DISTINCT a.transaction_id,
b.currency_id,
h.SIG_CURRENCY_CODE,
b.charge_id,
c.charge_type_id,
d.charge_group,
e.account_name,
f.sig_entity_label,
e.trading_userid,
e.exchange_id,
e.tradeable_instr_name,
TO_CHAR (e.create_ts, 'HH24:MI:SS'),
g.underlying_sym_bloomberg,
g.fut_expiration_date,
e.trade_date,
a.rate * a.basis_value AS dma_fee,
SUM (A.RATE * A.BASIS_VALUE) OVER () AS DMA_FEE_TOTAL,
-- this:
ROW_NUMBER () OVER (PARTITION BY e.pb_trans_id ORDER BY e.create_ts DESC) rn
FROM repldoadm.ire_estimate_trans_map a
LEFT JOIN repldoadm.ire_charges_estimate b
ON a.estimate_id = b.estimate_id
LEFT JOIN repldoadm.ire_charges_lu c
ON b.charge_id = c.charge_id
LEFT JOIN repldoadm.ire_charge_types_lu d
ON c.charge_type_id = d.charge_type_id
LEFT JOIN repldoadm.vw_ire_trade_transactions e
ON a.transaction_id = e.pb_trans_id
)
SELECT t.*
FROM temp t
WHERE t.rn = 1
Комментарии:
1. Вы ошибаетесь. Здесь не должно быть никаких
GROUP BY
оговорок. Я полагаю, вы следили за пунктом О ПРЕВЫШЕНИИ СУММЫ.2. Упс! Аналитическая форма функции СУММЫ! Я следил за этим, я ошибся, меня предупредили, я все исправил. Спасибо тебе, @Торстен!
3. @Littlefoot спасибо за это. Поразмыслив, я бы на самом деле хотел отфильтровать запись, которую я возвращаю, по критерию. Я также обновил код в своем первоначальном фрагменте, чтобы предоставить то, что я использую сейчас. У меня есть новый оператор СОЕДИНЕНИЯ СЛЕВА, чтобы ввести поле времени, и это на самом деле то, что заставляет меня вводить несколько записей, когда я хочу только одну (только для этого соединения). Как бы я отфильтровал этот оператор соединения, чтобы он возвращал запись с последней отметкой времени в этом поле?