开发者

Combining two already working ORACLE queries

开发者 https://www.devze.com 2023-04-02 11:40 出处:网络
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.

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  
/
0

精彩评论

暂无评论...
验证码 换一张
取 消