I'd like to ask for help with the two queries below. They work like a charm separately, now I want them to work together.
Both of them serve a loyalty card database.
The first one gets various information related to a user based on their unique cardnumber (%1111%, %2222%, %3333% in the example below) and returns the rows in the custom order that the cardnumbers were provided in.
SELECT cardnumber, first_name || ' ' || last_name
FROM (
SELECT cardnumber, first_name, last_name, c.OrderNo
FROM ag_cardholder ch, (SELECT '%1111%' cardmask, 1 OrderNo from dual
UNION ALL
SELECT '%2222%', 2 OrderNo from dual
UNION ALL
SELECT '%3333%', 3 OrderNo from dual
) c
WHERE ch.cardnumber LIKE c.cardmask
Order by c.OrderNo
) t
The second code returns the current point balance of a card based on the cardnumber and 开发者_开发技巧the type of the terminal last used to write the points on the card. There are two types of terminals that calculate the actual balance differently (one of them needs the number in the balance column, the other needs to sum the balance and total_points columns).
SELECT *
FROM
(SELECT
cardnumber,
(SELECT last_name || ' ' || first_name FROM ag_cardholder WHERE cardnumber = '1111'),
CASE
WHEN terminal_id LIKE 'AGHUPR9%' THEN card_balance
WHEN terminal_id LIKE 'AGHUPR7%' THEN card_balance + total_points
END
FROM ag_tranzakcio
WHERE cardnumber = '1111'
ORDER BY tran_date DESC)
WHERE ROWNUM = 1
What I want is a query that does both of these tasks: gets the cardnumbers in the provided order and returns some user information along with the current balance in the same order. Your help would be much appreciated.
UPDATE: Unfortunately I'm not familiar enough with ORACLE to come up with even a trial-and-error solution so I depend on your insight now.
SELECT cardnumber, name, balance, OrderNo
FROM
(
SELECT
ch.cardnumber cardnumber,
ch.first_name || ' ' || ch.last_name name,
CASE WHEN t.terminal_id LIKE 'AGHUPR9%' THEN t.card_balance
WHEN t.terminal_id LIKE 'AGHUPR7%' THEN t.card_balance + t.total_points
END balance,
rank () over (partition by ch.cardnumber order by t.tran_date DESC) rank,
c.OrderNo as OrderNo
FROM ag_cardholder ch
JOIN (SELECT '%1111%' cardmask, 1 OrderNo from dual
UNION ALL
SELECT '%2222%', 2 OrderNo from dual
UNION ALL
SELECT '%3333%', 3 OrderNo from dual
) c ON ch.cardnumber like c.cardmask
JOIN ag_tranzakcio t ON ch.cardnumber = t.cardnumber
)
WHERE rank = 1
ORDER BY OrderNo
EDIT: Assuming the ag_tranzakcio.id field is a reliable incrementing key, this could work:
SELECT cardnumber, name, balance, OrderNo
FROM
(
SELECT
ch.cardnumber cardnumber,
ch.first_name || ' ' || ch.last_name name,
CASE WHEN t.terminal_id LIKE 'AGHUPR9%' THEN t.card_balance
WHEN t.terminal_id LIKE 'AGHUPR7%' THEN t.card_balance + t.total_points
END balance,
rank () over (partition by ch.cardnumber order by t.id DESC) rank,
c.OrderNo as OrderNo
FROM ag_cardholder ch
JOIN (SELECT '%1111%' cardmask, 1 OrderNo from dual
UNION ALL
SELECT '%2222%', 2 OrderNo from dual
UNION ALL
SELECT '%3333%', 3 OrderNo from dual
) c ON ch.cardnumber like c.cardmask
JOIN ag_tranzakcio t ON ch.cardnumber = t.cardnumber
)
WHERE rank = 1
ORDER BY OrderNo
The revised requirement is to return only the most recent transaction for each card. This can be done by using the analytic function RANK() to sort the transactions, and then applying a wrapping query to filter on the calculated rank.
select cardnumber
, card_holder
, txn_amount
from
(
SELECT ch.cardnumber
, ch.first_name || ' ' || ch.last_name as card_holder
, CASE
WHEN txn.terminal_id LIKE 'AGHUPR9%' THEN txn.card_balance
WHEN txn.terminal_id LIKE 'AGHUPR7%' THEN txn.card_balance + txn.total_points
END as txn_amount
, rank () over (partition by ch.cardnumber order by txn.tran_date DESC) as rnk
, c.orderno
FROM ag_cardholder ch
join (SELECT '%1111%' cardmask, 1 OrderNo from dual
UNION ALL
SELECT '%2222%', 2 OrderNo from dual
UNION ALL
SELECT '%3333%', 3 OrderNo from dual
) c
on (ch.cardnumber LIKE c.cardmask)
join ag_tranzakcio txn
on (ch.cardnumber = txn.cardnumber)
)
where rnk=1
order by orderno, cardnumber
/
精彩评论