简体   繁体   中英

Aggregate sql query not working if select statement contains columns of type DATE

I want to select a single record with the latest value on the version column. However If I include the retrn_period column which is of type date my query returns multiple records.

SELECT rdo_code, batch_no, reference_no, dln, retrn_seq_num, ftype_code, tin, 
    branch_code, tax_type, retrn_period, Max(version)
FROM   rfp_returns_ref 
WHERE  tin = '000079108' 
AND    ftype_code = '1702EX' 
AND    Upper(status) = Upper('POSTED') 
group by rdo_code, batch_no,reference_no, dln, 
    retrn_seq_num, ftype_code, tin, branch_code, tax_type, retrn_period;

If I include the retrn_period column ... my query returns multiple records.

By including the retrn_period column you are changing the non-aggregated projection of the query, so now you get the maximum version for each distinct date in the result set.

You want to show the date of the latest version? Assuming your retrn_period increases alongside the version this would work:

SELECT rdo_code, batch_no, reference_no, dln, retrn_seq_num, ftype_code, tin, 
    branch_code, tax_type
       , max(retrn_period) as retrn_period
       , max(version) as version
FROM   rfp_returns_ref 
WHERE  tin = '000079108' 
AND    ftype_code = '1702EX' 
AND    Upper(status) = Upper('POSTED') 
group by rdo_code, batch_no,reference_no, dln, 
    retrn_seq_num, ftype_code, tin, branch_code, tax_type;

A more general solution which would work for something which can't be aggregate, say name , would be to use a subquery with an analytic function...

SELECT sq.rdo_code, sq.batch_no, sq.reference_no, sq.dln, sq.retrn_seq_num, sq.ftype_code, sq.tin, 
    sq.branch_code, sq.tax_type
       , sq.retrn_period
       , sq.name
       , sq.version
from (    
    SELECT rdo_code, batch_no, reference_no, dln, retrn_seq_num, ftype_code, tin, 
            branch_code, tax_type
               , retrn_period
               , version
               , name
               , rank() over (partition by rdo_code, batch_no,reference_no, dln, 
            retrn_seq_num, ftype_code, tin, branch_code, tax_type
                    order by version desc ) as rn
        FROM   rfp_returns_ref 
        WHERE  tin = '000079108' 
        AND    ftype_code = '1702EX' 
        AND    Upper(status) = Upper('POSTED') 
        ) sq
where sq.rn = 1 ;

If you're using Oracle 12c you can use the fetch limiting syntax, which is a lot simpler:

SELECT rdo_code, batch_no, reference_no, dln, retrn_seq_num, ftype_code, tin, 
    branch_code, tax_type
       , retrn_period
       , version
FROM   rfp_returns_ref 
WHERE  tin = '000079108' 
AND    ftype_code = '1702EX' 
AND   order by version desc 
fetch first 1 row only;

If you want to select a sinle record - with the highest version number - then I don't think you need to group any thing at all.

Ordering the rows by the version number and grabbing the top 1 should do it:

SELECT
    rdo_code,
    batch_no,
    reference_no,
    dln,
    retrn_seq_num,
    ftype_code,
    tin,
    branch_code,
    tax_type
    retrn_period,
    version
FROM rfp_returns_ref 
WHERE
    tin = '000079108' 
    AND ftype_code = '1702EX' 
    AND UPPER(status) = UPPER('POSTED')
ORDER BY version DESC
FETCH FIRST 1 ROWS ONLY;

This query assumes that you are running Oracle 12c.

You can also use rownum=1

SELECT
    rdo_code,
    batch_no,
    reference_no,
    dln,
    retrn_seq_num,
    ftype_code,
    tin,
    branch_code,
    tax_type
    retrn_period,
    version
FROM rfp_returns_ref 
WHERE
    tin = '000079108' 
    AND ftype_code = '1702EX' 
    AND UPPER(status) = UPPER('POSTED')
AND rownum=1
ORDER BY version DESC;
---------------------------------------------------------------------------------------
or subquery like

SELECT
    rdo_code,
    batch_no,
    reference_no,
    dln,
    retrn_seq_num,
    ftype_code,
    tin,
    branch_code,
    tax_type
    retrn_period,
    version
FROM rfp_returns_ref a
WHERE
    tin = '000079108' 
    AND ftype_code = '1702EX' 
    AND UPPER(status) = UPPER('POSTED')
AND a.version = (SELECT Max(b.version) 
                   FROM rfp_returns_ref b 
                  WHERE b.tin = a.tin
                    AND b.ftype_code = a.ftype_code
                    AND b.UPPER(status) = UPPER(a.status));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM