2

I'm having a problem with this query. I want to make an operation for my payroll system. I Here is my query which doesn't work.

Query:

select
    hrrawd_timein,
    hrrawd_shiftin,
    (
      (extract(hour from (hrrawd_timein::time))
      - extract(hour from (hrrawd_shiftin::time))
      )::numeric
    ) AS shiftinhours,
    (
      (extract(minute from (hrrawd_timein::time))
      - extract(minute from (hrrawd_shiftin::time))
      )::numeric
    ) AS shiftinminutes,
    (
      ((extract(hour from (hrrawd_timein::time))
      - extract(hour from (hrrawd_shiftin::time)
      ))*60)::numeric
    )
    + 
    (
      (extract(minute from (hrrawd_timein::time))
      - extract(minute from (hrrawd_shiftin::time))
      )::numeric
    ) AS Total,
    case
      when (Total >0) then 'Late' 
      else 'EARLY'
    end as remarks
  FROM hr.hrrawd;

Error:

> ERROR:  column "total" does not exist LINE 7: case when (Total >0)
> then 'Late'

3 Answers 3

4

I suggest to use common table expressions when you need precalculated columns:

with cte1 as (
    select
        hrrawd_timein, hrrawd_shiftin,
        (
           extract(hour from (hrrawd_timein::time)) -
           extract(hour from (hrrawd_shiftin::time))
        )::numeric as shiftinhours,
        (
           extract(minute from (hrrawd_timein::time)) -
           extract(minute from (hrrawd_shiftin::time))
        )::numeric as shiftinminutes
    from hr.hrrawd
), cte2 as (
    select
        *,
        shiftinhours * 60 + shiftinminutes as [total]
   from cte1
)
select
    *,
    case when [total] > 0 then 'Late' else 'Early' end as remarks
from cte2

I think it's much cleaner than subqueries. You can also chain as many CTE as you want, and it helps you to keep DRY principle - note how shiftinminutes and shiftinhours calculated just one time instead of two times. Readability counts, don't do the calculation twice, it will be hard to maintain in the future.

BTW, take a look at interval data type in PostgreSQL, you can extract hours and minutes from it

Sign up to request clarification or add additional context in comments.

1 Comment

Thankyou sir but your code has an error "ERROR: syntax error at or near "as" LINE 7: )::numeric) as shiftinhours,"
1

Answer:

select
    *,
    case when (Total >0) then 'Late' 
     else 'EARLY' end as remarks
from (
    select  hrrawd_timein, hrrawd_shiftin,
    ((extract(hour from (hrrawd_timein::time)) - extract(hour from (hrrawd_shiftin::time)))::numeric) AS shiftinhours,
    ((extract(minute from (hrrawd_timein::time)) - extract(minute from (hrrawd_shiftin::time)))::numeric) AS shiftinminutes,
    (((extract(hour from (hrrawd_timein::time)) - extract(hour from (hrrawd_shiftin::time)))*60)::numeric)
     + 
     ((extract(minute from (hrrawd_timein::time)) - extract(minute from (hrrawd_shiftin::time)))::numeric) AS Total
    FROM hr.hrrawd) a;

1 Comment

Hello sir, It is possible instead of this (((EXTRACT(HOUR FROM (hrrawd_timein::TIME)) - EXTRACT(HOUR FROM (hrrawd_shiftin::TIME)))*60)::NUMERIC) + ((EXTRACT(MINUTE FROM (hrrawd_timein::TIME)) - EXTRACT(MINUTE FROM (hrrawd_shiftin::TIME)))::NUMERIC) AS Total I'm using the ALIAS for the formula of total? for example "(shiftinhours + shiftinminutes) as Total" is that possible?
1

Standard SQL doesn't allow a column alias to be used in any other place but ORDER BY.

You need to cut&paste the calculation or better use a Derived Table:

SELECT
   hrrawd_timein, hrrawd_shiftin, 
   shiftinhours,
   shiftinminutes,
   Total,
   CASE WHEN (Total >0) THEN 'Late' ELSE 'EARLY' END AS remarks
FROM
 (
    SELECT  hrrawd_timein, hrrawd_shiftin, 
       ((EXTRACT(HOUR FROM (hrrawd_timein::TIME)) - EXTRACT(HOUR FROM (hrrawd_shiftin::TIME)))::NUMERIC) AS shiftinhours,
       ((EXTRACT(MINUTE FROM (hrrawd_timein::TIME)) - EXTRACT(MINUTE FROM (hrrawd_shiftin::TIME)))::NUMERIC) AS shiftinminutes,
       (((EXTRACT(HOUR FROM (hrrawd_timein::TIME)) - EXTRACT(HOUR FROM (hrrawd_shiftin::TIME)))*60)::NUMERIC)
        + ((EXTRACT(MINUTE FROM (hrrawd_timein::TIME)) - EXTRACT(MINUTE FROM (hrrawd_shiftin::TIME)))::NUMERIC) AS Total
    FROM hr.hrrawd
 ) AS dt

4 Comments

You can use alias also in GROUP BY, e.g.: select t as d from generate_series(1,10,1) t group by d
@Tomas Greif: That's why i said "Standard SQL" :-) Some DBMSes allow it to be used in other places, too. But AFAIK only Access and Teradata allow in SELECT/WHERE.
Hello sir, It is possible instead of this (((EXTRACT(HOUR FROM (hrrawd_timein::TIME)) - EXTRACT(HOUR FROM (hrrawd_shiftin::TIME)))*60)::NUMERIC) + ((EXTRACT(MINUTE FROM (hrrawd_timein::TIME)) - EXTRACT(MINUTE FROM (hrrawd_shiftin::TIME)))::NUMERIC) AS Total I'm using the ALIAS for the formula of total? for example "(shiftinhours + shiftinminutes) as Total" is that possible?
Yes, but then you can't use the "Total" alias in the CASE unless you nest it in another Derived Table.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.