views:

87

answers:

4

my table have several records which has the same MemberID. i want to result out only one record.

select DISTINCT(MemberID)  from AnnualFees;

then result will come. but i want to show the other column data also but when i do this

select DISTINCT(MemberID),StartingDate,ExpiryDate,Amount  from AnnualFees;

all the details including same MemberID data also displaying.

can someone help me.

A: 

select DISTINCT MemberID,StartingDate,ExpiryDate,Amount from AnnualFees;

remove paranthesis

KoolKabin
This will return one row for *every permutation* of MemberID,StartingDate,ExpiryDate and Amount
APC
+2  A: 

You need to select which of the rows with duplicate MemberIDs to return in some way. This will get the row with the greatest startingDate.

SELECT MemberID,StartingDate,ExpiryDate,Amount 
FROM AnnualFees af
WHERE NOT EXISTS (
        SELECT * from AnnualFees af2 
        WHERE af2.MemberID = af.MemberID 
        AND af2.StartingDate > af.StartingDate)
Martin Smith
+4  A: 

Assuming you just want any row at random for each memberid than you can do this:

select memberid, this, that, theother
from
(
select memberid, this, that, theother,
       row_number() over (partition by memberid order by this) rn
from   annualfees
)
where rn = 1;

If you wanted a specific row per memberid, e.g. the one with the most recent StartDate then you could modify it to:

select memberid, this, that, theother
from
(
select memberid, this, that, theother,
       row_number() over (partition by memberid order by StartDate desc) rn
from   annualfees
)
where rn = 1;
Tony Andrews
@Tony - RE: Your last query. Do you happen to know whether that is more efficient in Oracle than the version in my answer?
Martin Smith
@Martin Smith: The analytics solution (Tony's) will make a single pass on the data whereas yours will add a self-join (which may be a small overhead but will add work nonetheless). **In general**, Tony's solution will therefore be more efficient.
Vincent Malgrat
@Vincent Thanks, I was wondering about the row_number calculation. I presume that on the single pass it must create a bucket for each memberid, fill it with start dates and row ids, and then sort each bucket. If so I can see that would be quicker. If this guess as to how it works is totally wrong someone let me know!
Martin Smith
@Martin: One advantage of your solution is that Oracle doesn't have to read ALL rows of `annualfees` before returning rows: it can return rows as it finds those that satisfy the where clause whereas the analytics solution will have to read **ALL** rows before returning the first batch. If you are interested only in the first few rows (and if the table is really big), you will find your query returns faster. *(as always there is a tradeoff)*
Vincent Malgrat
+2  A: 

don't know if this is quite what you need, but you may need to look at GROUP BY instead of DISTINCT...

if you have several records with the same member id, you may need to specify exaclty how to identify the one you want from the others

eg to get each member`s last starting date:

SELECT memberid, max(startingdate)
FROM annualfees
GROUP BY memberid

but if you need to identify one record in this kind of way but also display the other columns, i think you may need to do some trickery like this...

eg sub-query the above SELECT with a join to join the other columns you want:

SELECT subq.memid, subq.startdate, a.expirydate, a.amount
FROM (
  SELECT memberid AS memid, max(startingdate) AS startdate
  FROM annualfees
  GROUP BY memberid ) subq
INNER JOIN annualfees a ON a.memberid = subq.memid 
               AND a.startingdate = subq.startdate

from start to finish, also showing data table (o/p was traced/grabbed using "SET VERIFY ON")...

-- show all rows
select *
from annualfees
order by memberid, startingdate
MEMBERID               STARTINGDATE              EXPIRYDATE           AMOUNT               
---------------------- ------------------------- -------------------- -------------------- 
1                      02-DEC-09                 05-FEB-10            111                  
1                      25-JUN-10                 25-JUN-11            222                  
2                      25-APR-10                 25-JUN-13            333                  

3 rows selected

/
-- show one member`s data using max(startingdate) as selector.
SELECT memberid, max(startingdate)
    FROM annualfees
    GROUP BY memberid
MEMBERID               MAX(STARTINGDATE)         
---------------------- ------------------------- 
1                      25-JUN-10                 
2                      25-APR-10                 

2 rows selected

/ 
-- show above data joined with the other columns.
SELECT subq.memid, subq.startdate, a.expirydate, a.amount
    FROM (
      SELECT memberid AS memid, max(startingdate) AS startdate
      FROM annualfees
      GROUP BY memberid ) subq
    INNER JOIN annualfees a ON a.memberid = subq.memid AND a.startingdate = subq.startdate
MEMID                  STARTDATE                 EXPIRYDATE           AMOUNT               
---------------------- ------------------------- -------------------- -------------------- 
1                      25-JUN-10                 25-JUN-11            222                  
2                      25-APR-10                 25-JUN-13            333                  

2 rows selected

/
MarkyBoyMark