Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL query that selects effective costing rate based on charge date

SQL novice here. I'm trying to generate a costing query that outputs employee time card information and calculates cost based on an effective employee costing rate.

My question is similar to the one asked here: Retro-active effective date changes with overlapping dates but I'm not dealing with retro-activity or overlapping date ranges.

Table examples (null values in the rate table indicate current rate):

CREATE TABLE Emp_Rate
(
    Emp int,
    Rate money,
    Rate_Start datetime,
    Rate_Exp datetime
)

CREATE TABLE Emp_Time
(
    Emp int,
    Chrg_Date datetime,
    Chrg_Code varchar(10),
    Chrg_Hrs decimal(8, 2)
)

Insert into Emp_Rate (Emp,Rate,Rate_Start,Rate_Exp) Values ('1','20','5/1/09','4/30/10')
Insert into Emp_Rate (Emp,Rate,Rate_Start,Rate_Exp) Values ('1','21','5/1/10','4/30/11')
Insert into Emp_Rate (Emp,Rate,Rate_Start,Rate_Exp) Values ('1','22','5/1/11',NULL)

Insert into Emp_Time (Emp,Chrg_Date,Chrg_Code,Chrg_Hrs) Values ('1','5/10/09','B','8')
Insert into Emp_Time (Emp,Chrg_Date,Chrg_Code,Chrg_Hrs) Values ('1','5/10/10','B','8')
Insert into Emp_Time (Emp,Chrg_Date,Chrg_Code,Chrg_Hrs) Values ('1','5/10/11','B','8')

The query (returns dupes caused by multiple rate entries(obviously)):

Select  Emp_Time.Emp,
        Cast(Emp_Time.Chrg_Date as DATE) as 'Chrg_Date',
        Emp_Time.Chrg_Code,
        Emp_Time.Chrg_Hrs,
        Emp_Rate.Rate,
        Emp_Time.Chrg_Hrs * Emp_Rate.Rate as 'Cost'

From    Emp_Time inner join
        Emp_Rate on Emp_Rate.Emp = Emp_Time.Emp

Order By [Emp],[Chrg_Date]

Desired output:

Emp Chrg_Date   Chrg_Code   Chrg_Hrs    Rate    Cost
1   2009-05-10  B           8.00        20.00   160.00
1   2010-05-10  B           8.00        21.00   168.00
1   2011-05-10  B           8.00        22.00   176.00

I've gone around in circles using the Between operator in a sub query to isolate the correct rate based on the charge date, but have not had any luck.

I appreciate any help!

like image 963
Jaxaeon Avatar asked Apr 17 '12 18:04

Jaxaeon


People also ask

How do you find the max effective date in SQL?

If you want a the max effdt even when the only effective date for the tree is future, simply remove the effdt/sysdate criteria entirely from the SQL. If you want the max effdt <= sysdate when there is an effdt <= sysdate but you want the min effdt when there are only future effdt, it gets more complicated.

How do I update a price by 10% in SQL?

The standard way of expressing this is: update products set price = price * 1.1 where prod_name like 'HP%'; The from clause is not necessary in this case.


1 Answers

You didn't specify the DBMS type the answer below is for sql-server. I am sure there are other ways to do this but this way will replace the null Rate_Exp date with the current date.

Select  et.Emp,
        Cast(et.Chrg_Date as DATEtime) as 'Chrg_Date',
        et.Chrg_Code,
        et.Chrg_Hrs,
        er.Rate,
        et.Chrg_Hrs * er.Rate as 'Cost'
From  Emp_Time et
inner join 
(
    SELECT Emp
        , Rate
        , Rate_Start
        , CASE
            WHEN Rate_Exp is Null
            THEN Convert(varchar(10), getdate(), 101)
            ELSE Rate_Exp
          END as Rate_Exp
    FROM Emp_Rate 
)er 
    on er.Emp = et.Emp
WHERE (et.Chrg_Date BETWEEN er.Rate_Start AND er.Rate_Exp)
Order By et.Emp,et.Chrg_Date

OR use the CASE Statement in your WHERE Clause:

Select  et.Emp,
        Cast(et.Chrg_Date as DATEtime) as 'Chrg_Date',
        et.Chrg_Code,
        et.Chrg_Hrs,
        er.Rate,
        et.Chrg_Hrs * er.Rate as 'Cost'
From  Emp_Time et
inner join Emp_Rate er
    on er.Emp = et.Emp
WHERE (et.Chrg_Date 
        BETWEEN er.Rate_Start 
                AND CASE WHEN er.Rate_Exp Is Null 
            THEN  Convert(varchar(10), getdate(), 101)
            ELSE er.Rate_Exp END)
like image 172
Taryn Avatar answered Oct 19 '22 18:10

Taryn