Get Latest Rates For Each Distinct Rate Name - sql

RateName Rate EffectiveDate
-------- ---- -------------
RateOne 400 2011-01-05
RateOne 410 2011-06-31
RateTwo 147 2010-09-21
RateThree 68 2011-07-14
RateTwo 100 2011-10-30
If I have data such as the above, how can I run a query such that I'll have these as results:
RateName Rate EffectiveDate
-------- ---- -------------
RateOne 410 2011-06-31
RateThree 68 2011-07-14
RateTwo 100 2011-10-30
Basically, I just need the latest rates for each distinct rate name.

You can try this:
SELECT A.*
FROM YourTable A
INNER JOIN ( SELECT RateName, MAX(EffectiveDate) AS MaxDate
FROM YourTable
GROUP BY RateName) B
ON A.RateName = B.RateName AND A.EffectiveDate = B.MaxDate

Related

SQL Query to display timekeeping table

I have a table like this
id Marca CodCartela Line Post status Time
---- ------ ----------- ---- ---- ------ -----------------------
178 346 4516645709 AS01 55 1 2015-04-05 02:30:12.627
179 346 4516645709 AS01 55 0 2015-04-05 02:31:23.593
180 346 4516645709 AS01 88 1 2015-04-05 02:32:05.107
181 346 4516645709 AS01 88 0 2015-04-05 02:32:22.060
Status 1 means IN and status 0 means OUT.
What I want is to display in and out time on the same line for each person.
Example
id Marca CodCartela Line Post status TimeIN TimeOUT
---- ---------------- ---- ---- ------ -----------------------------------------
178 346 4516645709 AS01 55 1 2015-04-05 02:30:12.627 2015-04-05 02:31:23.593
Is this possible or I need to rethink all the timekeeping aplications :(
This will track each person's Ins and Outs. Just switch yourTable in the CTE to your actual table name.
WITH CTE_yourTable
AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Marca ORDER BY [Time]) activity_num
FROM yourTable
)
SELECT A.ID,
A.Marca,
A.CodCartela,
A.[Line],
A.[Post],
--A.[Status],
A.[Time] AS TimeIn,
B.[Time] AS [TimeOut]
FROM CTE_yourTable A
LEFT JOIN CTE_yourTable B
ON A.Marca = B.Marca
AND A.activity_num = B.activity_num - 1
WHERE A.[Status] = 1
Results:
ID Marca CodCartela Line Post TimeIn TimeOut
----------- ----------- --------------------------------------- ---- ----------- ---------------------- ----------------------
178 346 4516645709 AS01 55 2015-04-0502:30:12.627 2015-04-0502:31:23.593
180 346 4516645709 AS01 88 2015-04-0502:32:05.107 2015-04-0502:32:22.060
Its simple use conditional Aggregate.
SELECT marca,
codcartela,
line,
post,
Max(CASE WHEN status = 1 THEN time END) AS TimeIN,
Max(CASE WHEN status = 0 THEN time END) AS TimeOUT
FROM yourtable
GROUP BY marca,
codcartela,
line,
post
Assuming that the combination post, status is unique you can do a join:
select
t1.*
,t2.Time as timeOut
from tab t1
left join tab t2
on t1.post = t2.post
and t2.status = 0
where t1.status = 1
Otherwise you might have to add additional conditions.
I don't know exactly how is the schema structure, and didn't get you well, I'm not sure but according to your sample data and desired output I think you want something like this:
select t1.marca,
t1.codcartela,
t1.line,
t1.post,
t1.time as TimeIN,
t2.time as TimeOUT
FROM table_name t1
LEFT OUTER JOIN table_name t2 on t1.post=t2.post
and t1.marca = t2.marca
WHERE t1.status=1 and isnull(t2.status,0)=0
Edit: changed join column to marca as mentioned it is for person

get multiple column from both table by joining a table on the basis of other max table column

1) vendor table
--------------------------------------------
VENDid VENDname
--- -----
1 ABC
2 XYZ
3 WXY
2)purchase table
---------------------------------------------
VENDid Purchasedate
------ ------------
1 12-01-2012
1 10-11-2013
2 22-02-2014
2 11-04-2014
3 10-05-2014
3 11-06-2014
1 14-06-2014
output(list all rows of vendor table and only max(purchasedate) from purchase table)
---------------------------------------------
VENDid VENDname PurchaseDate
------- -------- -------------
1 ABC 14-06-2014
2 XYZ 11-04-2014
3 WXY 11-06-2014
i got some queries like to solve previous problem-
SELECT v.VendID, VendName, Max(PurchaseDate)
FROM vendor v
INNER JOIN purchase p
ON v.VendID = p.VendID
Group By v.VendID, VendName
select VENDid, VENDname,
(select top 1 purchaseDate from purchase p
where p.VENDid=v.VENDid order by purchaseDate desc) as 'Purchase date'
from Vendor v
Que. If i will add some more column in purchase table like -
2)purchase table
------------------------------------------
VENDid Purchasedate amount_paid
------ ------------ ------------
1 12-01-2012 10000
1 10-11-2013 20000
2 22-02-2014 15000
2 11-04-2014 30000
3 10-05-2014 80000
3 11-06-2014 17000
1 14-06-2014 28000
and i want amount_paid along with previous output like-
---------------------------------------------
VENDid VENDname PurchaseDate amount_paid
------- -------- ------------- -------------
1 ABC 14-06-2014 28000
2 XYZ 11-04-2014 30000
3 WXY 11-06-2014 17000
then what will be query..
You appear to be using SQL Server. If so, you can use cross apply:
select v.VENDid, v.VENDname, p.PurchaseDate, p.Amount_Paid
from Vendor v cross apply
(select top 1 p.*
from purchase p
where p.VENDid = v.VENDid
order by p.purchaseDate desc
) p ;

Finding minimum from column value between group of rows

I have a table with six columns:
EKey ABC XYZ DOB My_Min Row_Num
---- ---- --- ---- ------ -------
101 AB10 123 1946 100 1
103 AB10 123 1946 200 2
201 TN10 456 1955 150 1
220 TN10 456 1955 240 2
216 TN10 456 1955 80 3
214 TN10 456 1955 80 4
I want to compute a new column Required_Min which should have the values as shown below:
EKey ABC XYZ DOB My_Min Row_Num Required_Min
---- ---- --- ---- ------ ------- ------------
101 AB10 123 1946 100 1 100
103 AB10 123 1946 200 2 100
201 TN10 456 1955 150 1 80
220 TN10 456 1955 240 2 80
216 TN10 456 1955 80 3 80
214 TN10 456 1955 80 4 80
Im using SQL for this, i.e., SSMS. Please help.
You can JOIN the table back to itself using the MIN aggregate:
select t.ekey, t.abc, t.xyz, t.dob, t.my_min, t.rownum,
t2.required_min
from yourtable t
join (
select ekey, min(my_min) required_min
from yourtable
group by ekey
) t2 on t.ekey = t2.ekey
If your uniqueness is based on ABC+XYZ+DOB, you can do the following:
with TableMin as
(select ABC,XYZ,DOB,min(My_min) as My_min
group by ABC,XYZ,DOB
from Table1)
update t1 set t1.Required_Min=tm.My_min
from Table1 t1 inner join TableMin tm on t1.ABC=tm.ABC and t1.XYZ=tm.XYZ and t1.DOB=tm.DOB
But this join is quite hard for server with big amount of data. If ABC+XYZ in unique key (or even ABC), use this instead of full ABC+XYZ+DOB.
This should give you the desired results:
select EKey = t.EKey ,
ABC = t.ABC ,
XYZ = t.XYZ ,
DOB = t.DOB ,
My_Min = t.My_Min ,
Row_Num = t.Row_Num ,
Required_Min = min(t.My_Min) over( partition by t.ABC , t.XYZ , t.DOB )
from dbo.my_table t
order by t.ABC ,
t.XYZ ,
t.DOB ,
t.Row_Num
If you actually want to add a new column to the table, then you'll need to do something like this:
alter table dbo.my_table add column Required_Min int null
go
update dbo.my_table
set Required_Min = s.Required_Min
from dbo.my_Table t
join ( select ABC , XYZ , DOB , Required_Min = min(My_Min)
from dbo.my_table
group by ABC , XYZ , DOB
) s on s.ABC = t.ABC
and s.XYZ = t.XYZ
and x.DOB = t.DOB
go
alter table dbo.my_table alter column Required_Min int not null
go
The update could also be standard SQL, using a correlated subquery instead of a derived table. Assuming decent indexing, the execution plans shouldn't vary too much:
update dbo.my_table
set Required_Min = ( select min(My_Min)
from dbo.my_table x
where x.ABC = dbo.my_table.ABC
and x.XYZ = dbo.my_table.XYZ
and x.DOB = dbo.my_table.DOB
)
I'm assuming ssms implies sql server. I'm assuming that you want the minimum "my_min" from rows with the same "RowNum"
try this:
update table_name as outer
set outer.Required_Min = (select min(My_Min)
from table_name as inner
where inner.RowNum = outer.RowNum)
-edit-
new assumption: ABC+XYZ+DOB form a natural key:
update table_name as outer
set outer.Required_Min = ( select min(My_Min)
from table_name as inner
where inner.ABC = outer.ABC
and inner.XYZ = outer.XYZ
and inner.DOB = outer.DOB )
Looks like a job for analitical func PARTITION BY:
select EKey, ABC, XYZ, DOB, My_Min, Row_Num,
min(My_Min) OVER (PARTITION BY ABC, XYZ, DOB) as Required_Min
from Stats
Also, I recommend you to do not store 'Required_Min' as a column, but compute it on demand in a view or query. Otherwise, you'll have to spend your time on providing data relevance (triggers or smth ). So, I would build specific inedexes instead to improve query perfomance.

SQL Server : take 1 to many record set and make 1 record per id

I need some help. I need to take the data from these 3 tables and create an output that looks like below. The plan_name_x and pending_tallyx columns are derived to make one line per claim id. Each claim id can be associated to up to 3 plans and I want to show each plan and tally amounts in one record. What is the best way to do this?
Thanks for any ideas. :)
Output result set needed:
claim_id ac_name plan_name_1 pending_tally1 plan_name_2 Pending_tally2 plan_name_3 pending_tally3
-------- ------- ----------- -------------- ----------- -------------- ----------- --------------
1234 abc cooks delux_prime 22 prime_express 23 standard_prime 2
2341 zzz bakers delpux_prime 22 standard_prime 2 NULL NULL
3412 azb pasta's prime_express 23 NULL NULL NULL NULL
SQL Server 2005 table to use for the above result set:
company_claims
claim_id ac_name
1234 abc cooks
2341 zzz bakers
3412 azb pasta's
claim_plans
claim_id plan_id plan_name
1234 101 delux_prime
1234 102 Prime_express
1234 103 standard_prime
2341 101 delux_prime
2341 103 standard_prime
3412 102 Prime_express
Pending_amounts
claim_id plan_id Pending_tally
1234 101 22
1234 102 23
1234 103 2
2341 101 22
2341 103 2
3412 102 23
If you know that 3 is always the max amount of plans then some left joins will work fine:
select c.claim_id, c.ac_name,
cp1.plan_name as plan_name_1, pa1.pending_tally as pending_tally1,
cp2.plan_name as plan_name_2, pa2.pending_tally as pending_tally2,
cp3.plan_name as plan_name_3, pa3.pending_tally as pending_tally3,
from company_claims c
left join claim_plans cp1 on c.claim_id = cp1.claim_id and cp1.planid = 101
left join claim_plans cp2 on c.claim_id = cp2.claim_id and cp2.planid = 102
left join claim_plans cp3 on c.claim_id = cp3.claim_id and cp3.planid = 103
left join pending_amounts pa1 on cp1.claim_id = pa1.claimid and cp1.planid = pa1.plainid
left join pending_amounts pa2 on cp2.claim_id = pa2.claimid and cp2.planid = pa2.plainid
left join pending_amounts pa3 on cp3.claim_id = pa3.claimid and cp3.planid = pa3.plainid
I would first join all your data so that you get the relevant columns: claim_id, ac_name, plan_name, pending tally.
Then I would add transform this to get plan name and plan tally on different rows, with a label tying them together.
Then it should be easy to pivot.
I would tie these together with common table expressions.
Here's the query:
with X as (
select cc.*, cp.plan_name, pa.pending_tally,
rank() over (partition by cc.claim_id order by plan_name) as r
from company_claims cc
join claim_plans cp on cp.claim_id = cc.claim_id
join pending_amounts pa on pa.claim_id = cp.claim_id
and pa.plan_id = cp.plan_id
), P as (
select
X.claim_id,
x.ac_name,
x.plan_name as value,
'plan_name_' + cast(r as varchar(max)) as label
from x
union all
select
X.claim_id,
x.ac_name,
cast(x.pending_tally as varchar(max)) as value,
'pending_tally' + cast(r as varchar(max)) as label
from x
)
select claim_id, ac_name, [plan_name_1], [pending_tally1],[plan_name_2], [pending_tally2],[plan_name_3], [pending_tally3]
from (select * from P) p
pivot (
max(value)
for label in ([plan_name_1], [pending_tally1],[plan_name_2], [pending_tally2],[plan_name_3], [pending_tally3])
) as pvt
order by pvt.claim_id, ac_name
Here's a fiddle showing it in action: http://sqlfiddle.com/#!3/68f62/10

Select column values not present in group by clause

I have a table consisting of customer purchase records having following columns
CUSTOMER TRANSDATE SALENUM STORE TRANSTYP PRICE
-------- --------- --------- ----- --------- ------
1 12-FEB-2013 777 O CASH 7.99
1 12-FEB-2013 777 O CASH 6.99
1 12-FEB-2013 778 O CARD 9.17
2 23-APR-2013 987 D CASH 7.65
1 15-MAY-2013 1098 T CARD 2.35
I want to aggregate over salenum i,e for each salenum, i want the total price, as well as the store, transtyp, transdate,customer values as these are same for a particular salenum
However if i use
select customer,transdate,salenum,store,transtyp,sum(price) from table1 group by salenum
Its obviously saying not a valid group by value. How to get the desired result?
SAMPLE RESULT:
CUSTOMER TRANSDATE SALENUM STORE TRANSTYP PRICE
-------- --------- --------- ----- --------- ------
1 12-FEB-2013 777 O CASH 15.98
1 12-FEB-2013 778 O CARD 9.17
All non-aggregated columns should be in the group by:
select customer,transdate,salenum,store,transtyp,sum(price)
from table1
group by customer,transdate,salenum,store,transtyp
SELECT CUSTOMER,TRANSDATE,SALENUM,STORE,TRANSTYP,SUM(PRICE)
FROM TABLE1
GROUP BY CUSTOMER,TRANSDATE,SALENUM,STORE,TRANSTYP
ORDER BY CUSTOMER
I using the order by clause because it will be in order and also in sequence.