Home » SQL & PL/SQL » SQL & PL/SQL » Return First and Last values?
Return First and Last values? [message #10062] Tue, 30 December 2003 06:16 Go to next message
Andrew
Messages: 144
Registered: March 1999
Senior Member
Hi,

I have a query in Access that returns the First value from a field, this is an example of the query in SQL from Access: -

SELECT SUM(TABLE.LOAD_CASH) AS SUMOFLOAD, FIRST(TABLE.LOAD_CASH) AS FIRSTOFLOAD

I want to do the same thing through SQL Navigator or SQLPlusW. I've looked at the documentation in particular FIRST_VALUE and I'm a little confused ;-)

Could some one show me an example or give an explaination, as the OVER part is the bit that I got lost on?

Regards
Re: Return First and Last values? [message #10068 is a reply to message #10062] Wed, 31 December 2003 00:07 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
In Oracle, you have to establish an order of values before you can identify which is first. Data is not automatically returned in the order inserted or any default order. If you use just the order by clause after over, then you get the first value when rows are placed in that order. For example, using the Oracle emp demo table, if you order it, by either empno or sal, the first row contains empno 7369 and sal 800 and those would be the first values, as shown in the example below:

scott@ORA92> -- first value of empno and first value of sal
scott@ORA92> -- when ordered by empno:
scott@ORA92> select deptno, empno, sal,
  2  	    first_value (empno) over (order by empno) as first_emp_by_empno,
  3  	    first_value (sal) over (order by empno) as first_sal_by_empno
  4  from   emp
  5  order  by empno
  6  /

    DEPTNO      EMPNO        SAL FIRST_EMP_BY_EMPNO FIRST_SAL_BY_EMPNO
---------- ---------- ---------- ------------------ ------------------
        20       7369        800               7369                800
        30       7499       1600               7369                800
        30       7521       1250               7369                800
        20       7566       2975               7369                800
        30       7654       1250               7369                800
        30       7698       2850               7369                800
        10       7782       2450               7369                800
        20       7788       3000               7369                800
        10       7839       5000               7369                800
        30       7844       1500               7369                800
        20       7876       1100               7369                800
        30       7900        950               7369                800
        20       7902       3000               7369                800
        10       7934       1300               7369                800

14 rows selected.

scott@ORA92> -- first value of empno and first value of sal
scott@ORA92> -- when ordered by sal:
scott@ORA92> select deptno, empno, sal,
  2  	    first_value (empno) over (order by sal) as first_emp_by_sal,
  3  	    first_value (sal) over (order by sal) as first_sal_by_sal
  4  from   emp
  5  order  by sal
  6  /

    DEPTNO      EMPNO        SAL FIRST_EMP_BY_SAL FIRST_SAL_BY_SAL
---------- ---------- ---------- ---------------- ----------------
        20       7369        800             7369              800
        30       7900        950             7369              800
        20       7876       1100             7369              800
        30       7521       1250             7369              800
        30       7654       1250             7369              800
        10       7934       1300             7369              800
        30       7844       1500             7369              800
        30       7499       1600             7369              800
        10       7782       2450             7369              800
        30       7698       2850             7369              800
        20       7566       2975             7369              800
        20       7788       3000             7369              800
        20       7902       3000             7369              800
        10       7839       5000             7369              800

14 rows selected.


If you add the partition by clause after over, then you get the first value for each partition. For example, if you partition by deptno, then you get the first empno or first sal for each deptno. I have added a row of hyphens to separate each deptno in the examples below for easier reading. Notice that the results are different, depending on whether you order by empno or sal:

scott@ORA92> -- first value of empno and first value of sal
scott@ORA92> -- for each deptno partition
scott@ORA92> -- when ordered by empno:
scott@ORA92> select deptno, empno, sal,
  2  	    first_value (empno) over (partition by deptno order by empno) as first_emp_by_empno,
  3  	    first_value (sal) over (partition by deptno order by empno) as first_sal_by_empno
  4  from   emp
  5  order  by deptno, empno
  6  /

    DEPTNO      EMPNO        SAL FIRST_EMP_BY_EMPNO FIRST_SAL_BY_EMPNO
---------- ---------- ---------- ------------------ ------------------
        10       7782       2450               7782               2450
        10       7839       5000               7782               2450
        10       7934       1300               7782               2450
----------------------------------------------------------------------
        20       7369        800               7369                800
        20       7566       2975               7369                800
        20       7788       3000               7369                800
        20       7876       1100               7369                800
        20       7902       3000               7369                800
----------------------------------------------------------------------
        30       7499       1600               7499               1600
        30       7521       1250               7499               1600
        30       7654       1250               7499               1600
        30       7698       2850               7499               1600
        30       7844       1500               7499               1600
        30       7900        950               7499               1600

14 rows selected.

scott@ORA92> -- first value of empno and first value of sal
scott@ORA92> -- for each deptno partition
scott@ORA92> -- when ordered by sal:
scott@ORA92> select deptno, empno, sal,
  2  	    first_value (empno) over (partition by deptno order by sal) as first_emp_by_sal,
  3  	    first_value (sal) over (partition by deptno order by sal) as first_sal_by_sal
  4  from   emp
  5  order  by deptno, sal
  6  /

    DEPTNO      EMPNO        SAL FIRST_EMP_BY_SAL FIRST_SAL_BY_SAL
---------- ---------- ---------- ---------------- ----------------
        10       7934       1300             7934             1300
        10       7782       2450             7934             1300
        10       7839       5000             7934             1300
----------------------------------------------------------------------
        20       7369        800             7369              800
        20       7876       1100             7369              800
        20       7566       2975             7369              800
        20       7788       3000             7369              800
        20       7902       3000             7369              800
----------------------------------------------------------------------
        30       7900        950             7900              950
        30       7521       1250             7900              950
        30       7654       1250             7900              950
        30       7844       1500             7900              950
        30       7499       1600             7900              950
        30       7698       2850             7900              950

14 rows selected.


It may be that first_value and last_value are not what you are looking for. You may be looking for min and max or greatest and least. Those of us reading this forum don't necessarily know Access. It would help if you would provide some sample data and what results you would like, based on that sample data.
Re: Return First and Last values? [message #10071 is a reply to message #10068] Wed, 31 December 2003 01:02 Go to previous messageGo to next message
Andrew
Messages: 144
Registered: March 1999
Senior Member
Barbara,

Many thanks for the reply and examples.

It is the First_Value & Last_Values I'm looking for, below is further information on what I'm trying to arrive at.

I have 4 tables: -

TB_TRANSACTIONS TR
TB_TRANS_CARDS TC
TB_CUSTOMERS CU
TB_CASHREGS CR

From which I would like to show one row of the following: -

Sum of TC.LOAD_CASH
First of TC.LOAD_CASH
Sum of TR.CARD_AMOUNT
First of TC.BAL_CASH
Last of TC.BAL_CASH
Last of TR.BOOKKEEPING_DATE
Fisrt of TC.BAL_CASH - First of TC.LOAD_CASH As Start_Bal

Joins: -

TR.ID = TC.TRANSACTION_ID
CR.ID = TR.CASHREG_ID
TR.CARD_NUM = CU.CARD_NUM

Criteria: -

WHERE TR.BOOKKEEPING_DATE BETWEEN (Date) AND (Date)
AND TR.CARD_NUM = (Card Number)

I hope this is of some help in explaining myself more clearly?

Regards,

Andrew

PS. How do I format my code in the message?
Re: Return First and Last values? [message #10072 is a reply to message #10071] Wed, 31 December 2003 02:41 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
You seemed to have missed the main point: first value or last value when ordered by what? There is no such thing as first value or last value until you establish an ordering. Do you want to order by bookkeeping_date? Once again, please supply some sample data and desired output based on that data, in order to clarify what you want.

To format your posts, you can use html tags. The simplest formatting consists of placing < pre > on the line above your code and < /pre > on the line below your code, but without any spaces. I had to add spaces in order for it to be visible.
Re: Return First and Last values? [message #10073 is a reply to message #10072] Wed, 31 December 2003 03:10 Go to previous messageGo to next message
Andrew
Messages: 144
Registered: March 1999
Senior Member
Barbara,

In that case it would be Order By BOOKKEEPING_DATE.

Here's some sample data: -
TB_CASHREGS

ID	CODE	DESCRIPTION
---------------------------
1	1	Till One
2	2	Till Two

TB_TRANSACTIONS

ID	CASHREG_ID	BOOKKEEPING_DATE	CARD_AMOUNT	CARD_NUM
------------------------------------------------------------------------
1	1		12/12/2003		0.35		004
2	2		12/12/2003		0.50		005
3	1		12/12/2003		0.75		005
4	1		13/12/2003		0.35		005
5	2		13/12/2003		0.35		005

TB_TRANS_CARDS

TRANSACTION_ID		LOAD_CASH	BAL_CASH
--------------------------------------------------
1					4.65
2			5.00		6.50
3					5.75
4					5.40
5			2.00		7.15

TB_CUSTOMERS

ID	CODE	CARD_NUM	DESCRIPTION
-------------------------------------------
1	20002	005		Joe



Output with following criteria: -
TR.BOOKKEEPING_DATE BETWEEN TO_DATE('12-12-2003', 'DD.MM.YYYY') AND TO_DATE('13-12-2003', 'DD.MM.YYYY')
AND TR.CARD_NUM = '005'

SumOfLOAD_CASH	 FistOfLOAD_CASH  SumofCARD_AMOUNT  FirstOfBAL_CASH   LastOfBAL_CASH   LastOfBOOKKEEPING_DATE   START_BAL
-------------------------------------------------------------------------------------------------------------------------
7.00		5.00			1.95		6.50		7.15		13/12/2003		1.50



Hope this helps?

Regards,

Andrew
Re: Return First and Last values? [message #10080 is a reply to message #10073] Wed, 31 December 2003 20:24 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
scott@ORA92> -- test data:
scott@ORA92> SELECT * FROM tb_cashregs
  2  /

        ID       CODE DESCRIPT
---------- ---------- --------
         1          1 Till One
         2          2 Till Two

scott@ORA92> SELECT * FROM tb_transactions
  2  /

        ID CASHREG_ID BOOKKEEPIN CARD_AMOUNT CAR
---------- ---------- ---------- ----------- ---
         1          1 12/12/2003         .35 004
         2          2 12/12/2003          .5 005
         3          1 12/12/2003         .75 005
         4          1 12/12/2003         .35 005
         5          2 12/12/2003         .35 005

scott@ORA92> SELECT * FROM tb_trans_cards
  2  /

TRANSACTION_ID  LOAD_CASH   BAL_CASH
-------------- ---------- ----------
             1                  4.65
             2          5        6.5
             3                  5.75
             4                   5.4
             5          2       7.15

scott@ORA92> SELECT * FROM tb_customers
  2  /

        ID       CODE CAR DES
---------- ---------- --- ---
         1       2002 005 Joe

scott@ORA92> -- joined and ordered data:
scott@ORA92> SELECT tc.load_cash,
  2  	    tr.card_amount,
  3  	    tc.bal_cash,
  4  	    tr.bookkeeping_date,
  5  	    tc.bal_cash - tc.load_cash
  6  FROM   tb_transactions tr,
  7  	    tb_trans_cards  tc,
  8  	    tb_customers    cu,
  9  	    tb_cashregs     cr
 10  WHERE  tr.id = tc.transaction_id
 11  AND    cr.id = tr.cashreg_id
 12  AND    tr.card_num = cu.card_num
 13  AND    tr.bookkeeping_date BETWEEN TO_DATE ('12-12-2003', 'DD-MM-YYYY')
 14  				AND	TO_DATE ('13-12-2003', 'DD-MM-YYYY')
 15  AND    tr.card_num = '005'
 16  ORDER  BY tr.bookkeeping_date
 17  /

 LOAD_CASH CARD_AMOUNT   BAL_CASH BOOKKEEPIN TC.BAL_CASH-TC.LOAD_CASH
---------- ----------- ---------- ---------- ------------------------
         5          .5        6.5 12/12/2003                      1.5
                   .75       5.75 12/12/2003
                   .35        5.4 12/12/2003
         2         .35       7.15 12/12/2003                     5.15

scott@ORA92> -- sums:
scott@ORA92> SELECT SUM (tc.load_cash)	 AS "SumOfLOAD_CASH",
  2  	    SUM (tr.card_amount) AS "SumOfCARD_AMOUNT"
  3  FROM   tb_transactions tr,
  4  	    tb_trans_cards  tc,
  5  	    tb_customers    cu,
  6  	    tb_cashregs     cr
  7  WHERE  tr.id = tc.transaction_id
  8  AND    cr.id = tr.cashreg_id
  9  AND    tr.card_num = cu.card_num
 10  AND    tr.bookkeeping_date BETWEEN TO_DATE ('12-12-2003', 'DD-MM-YYYY')
 11  				AND	TO_DATE ('13-12-2003', 'DD-MM-YYYY')
 12  AND    tr.card_num = '005'
 13  /

SumOfLOAD_CASH SumOfCARD_AMOUNT
-------------- ----------------
             7             1.95

scott@ORA92> -- first values, and last values:
scott@ORA92> SELECT FIRST_VALUE (tc.load_cash) OVER
  2  	      (ORDER BY tr.bookkeeping_date)   AS "FirstOfLOAD_CASH",
  3  	    FIRST_VALUE (tc.bal_cash) OVER
  4  	      (ORDER BY tr.bookkeeping_date)   AS "FirstOfBAL_CASH",
  5  	    LAST_VALUE (tc.bal_cash) OVER
  6  	      (ORDER BY tr.bookkeeping_date)   AS "LastOfBAL_CASH",
  7  	    LAST_VALUE (tr.bookkeeping_date) OVER
  8  	      (ORDER BY tr.bookkeeping_date)   AS "LastOfBOOKKEEING_DATE",
  9  	    ((FIRST_VALUE (tc.bal_cash) OVER
 10  	       (ORDER BY tr.bookkeeping_date))
 11  	    -(FIRST_VALUE (tc.load_cash) OVER
 12  	       (ORDER BY tr.bookkeeping_date))) AS "START_BAL"
 13  FROM   tb_transactions tr,
 14  	    tb_trans_cards  tc,
 15  	    tb_customers    cu,
 16  	    tb_cashregs     cr
 17  WHERE  tr.id = tc.transaction_id
 18  AND    cr.id = tr.cashreg_id
 19  AND    tr.card_num = cu.card_num
 20  AND    tr.bookkeeping_date BETWEEN TO_DATE ('12-12-2003', 'DD-MM-YYYY')
 21  				AND	TO_DATE ('13-12-2003', 'DD-MM-YYYY')
 22  AND    tr.card_num = '005'
 23  AND    ROWNUM = 1
 24  /

FirstOfLOAD_CASH FirstOfBAL_CASH LastOfBAL_CASH LastOfBOOK  START_BAL
---------------- --------------- -------------- ---------- ----------
               5             6.5            6.5 12/12/2003        1.5

scott@ORA92> -- sums, first values, and last values:
scott@ORA92> SELECT sums.sum_load_cash	       AS "SumOfLOAD_CASH",
  2  	    vals.first_load_cash       AS "FirstOfLOAD_CASH",
  3  	    sums.sum_card_amount       AS "SumOfCARD_AMOUNT",
  4  	    vals.first_bal_cash        AS "FirstOfBAL_CASH",
  5  	    vals.last_bal_cash	       AS "LastOfBAL_CASH",
  6  	    vals.last_bookkeeping_date AS "LastOfBOOKKEEPING_DATE",
  7  	    vals.start_bal
  8  FROM   (SELECT SUM (tc.load_cash)	 AS sum_load_cash,
  9  		    SUM (tr.card_amount) AS sum_card_amount
 10  	     FROM   tb_transactions tr,
 11  		    tb_trans_cards  tc,
 12  		    tb_customers    cu,
 13  		    tb_cashregs     cr
 14  	     WHERE  tr.id = tc.transaction_id
 15  	     AND    cr.id = tr.cashreg_id
 16  	     AND    tr.card_num = cu.card_num
 17  	     AND    tr.bookkeeping_date BETWEEN TO_DATE ('12-12-2003', 'DD-MM-YYYY')
 18  					AND	TO_DATE ('13-12-2003', 'DD-MM-YYYY')
 19  	     AND    tr.card_num = '005') sums,
 20  	    (SELECT FIRST_VALUE (tc.load_cash) OVER
 21  		      (ORDER BY tr.bookkeeping_date)	AS first_load_cash,
 22  		    FIRST_VALUE (tc.bal_cash) OVER
 23  		      (ORDER BY tr.bookkeeping_date)	AS first_bal_cash,
 24  		    LAST_VALUE (tc.bal_cash) OVER
 25  		      (ORDER BY tr.bookkeeping_date)	AS last_bal_cash,
 26  		    LAST_VALUE (tr.bookkeeping_date) OVER
 27  		      (ORDER BY tr.bookkeeping_date)	AS last_bookkeeping_date,
 28  		    ((FIRST_VALUE (tc.bal_cash) OVER
 29  			(ORDER BY tr.bookkeeping_date))
 30  		    -(FIRST_VALUE (tc.load_cash) OVER
 31  			(ORDER BY tr.bookkeeping_date))) AS start_bal
 32  	     FROM   tb_transactions tr,
 33  		    tb_trans_cards  tc,
 34  		    tb_customers    cu,
 35  		    tb_cashregs     cr
 36  	     WHERE  tr.id = tc.transaction_id
 37  	     AND    cr.id = tr.cashreg_id
 38  	     AND    tr.card_num = cu.card_num
 39  	     AND    tr.bookkeeping_date BETWEEN TO_DATE ('12-12-2003', 'DD-MM-YYYY')
 40  					AND	TO_DATE ('13-12-2003', 'DD-MM-YYYY')
 41  	     AND    tr.card_num = '005'
 42  	     AND    ROWNUM = 1) vals
 43  /

SumOfLOAD_CASH FirstOfLOAD_CASH SumOfCARD_AMOUNT FirstOfBAL_CASH LastOfBAL_CASH LastOfBOOK  START_BAL
-------------- ---------------- ---------------- --------------- -------------- ---------- ----------
             7                5             1.95             6.5            6.5 12/12/2003        1.5
Re: Return First and Last values? [message #10081 is a reply to message #10080] Wed, 31 December 2003 20:32 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
Note: The above solution only works if the bookkeeping_date contains a time component that makes each one unique. Otherwise, all the 12/12/2003 dates are the same and you may get the rows in any order. I assume that your bookkeeping_date is actually a date datatype and that only the date portion was displayed due to the nls_date_format.
Re: Return First and Last values? [message #10351 is a reply to message #10072] Fri, 16 January 2004 03:19 Go to previous message
corey lawson
Messages: 1
Registered: January 2004
Junior Member
FIRST() and LAST() are two Access-specific aggregate functions, which means you need to have a GROUP BY clause at the end of your query for the output to make logical sense.
Previous Topic: OWA_UTIL.CALENDARPRINT
Next Topic: Package javax.servlet.http not found in import.
Goto Forum:
  


Current Time: Thu Apr 25 17:24:23 CDT 2024