We have three ProductIDs and their prices are changing by Date
ProductID Price Date
1 100 2016-06-01
2 50 2016-06-05
3 10 2016-06-10
2 60 2016-06-15
1 110 2016-06-20
3 20 2016-06-25
How to select only last updated Price per each ProductID until 2016-06-20 inclusive to get the next output:
ProductID Price
3 10
2 60
1 110
I searched for answer but could't find the specific one.
Have a sub-query that returns each ProductID's last date (until 2016-06-20). Join with that result:
select t1.*
from tablename t1
join (select ProductID, max(Date) Date
from tablename
where Date <= '2016-06-20'
group by ProductID) t2
on t1.ProductID = t2.ProductID and t1.Date = t2.Date
ANSI SQL has date as reserved word, so you may need to delimit that column as "Date". Also ANSI SQL has date literals as date '2016-06-20'.
Related
I would need a help in the following scneario. I am using T-SQL
Following is my table details. Say the table name is #tempk
Customer Current_Month Contract Amount
201 2015-09-01 3 100
My requirement is to add 12 months from the current month.that is 2016-09-01. Assuming
I am getting the start date of the month. I need the data in the following format
Customer Renewal_Month Contract_months End_Month Amount
201 2015-09-01 3 2016-09-01 100
201 2015-12-01 3 2016-09-01 100
201 2015-03-01 3 2016-09-01 100
201 2015-06-01 3 2016-09-01 100
The contract column can have any values
The consquent records are incremental of contract columns from the previous records.
I am using the following query. I have a date dimension table called Dim_Date that has date,quareter,year,month etc..
WITH GetProrateCTE (Customer_ID,Renewal_Month,Contract_Months,End_Month,MRR) as
(SELECT Customer_ID,Renewal_Month,Contract_Months,DATEADD(month, 12,Renewal_Month) End_Month,MRR
from #tempk),
GetRenewalMonths (Customer_ID,Renewal_Month,Contract_Months,End_Month,MRR) as
(
SELECT A.Customer_ID,B.Month Renewal_Month,A.Contract_Months,A.End_Month,A.MRR
FROM GetProrateCTE A
INNER JOIN (SELECT Month from DW..Dim_Date B GROUP BY MONTH) B
ON B.Month between A.Renewal_Month and A.End_Month
)
SELECT G.Customer_ID,G.Renewal_Month,G.Contract_Months,G.End_Month,G.MRR
FROM GetRenewalMonths G
Could you please help me to achieve the result. Any help would be greatly appreciated.
I want to do this in Common table Expressions. or would it be better if I go cursor.
You can try in this way -
WITH CTE AS
(SELECT Customer,DATEADD(MM,DATEDIFF(MM,0,Current_Month), 0) AS Renewal_Month,Contract,DATEADD(YEAR,1,Current_Month) AS End_Month,Amount,1 AS Level FROM #tempk
UNION ALL
SELECT t.Customer,DATEADD(MONTH,t.Contract,c.Renewal_Month),t.Contract,DATEADD(YEAR,1,t.Current_Month) AS End_Month,t.Amount,Level + 1
FROM #tempk t join CTE c on t.customer = c.customer
WHERE Level < (12/t.Contract))
SELECT Customer,Renewal_Month,Contract AS Contract_months,End_Month,Amount
FROM CTE
Just append your logic of the date dimension table to this.
I'm working a query in SQL 2005.
I'm trying to get the latest date for a number column. The trick is there is another column (rate) that use the column date and I fetch the wrong column in the end.
An example will better explain my question.
This is my SQL table EmployeeRates:
----------------------------------
FkEmployee | Date | Rate | Number |
----------------------------------
1 2000 15 1.5
1 2001 16 1.5
1 2002 16 1.6
2 2000 12 1.5
2 2001 14 1.6
2 2002 15 1.6
So if I fetch the latest date, currently I have :
FkEmployee #1 = 2002 (which is correct because it's the latest date for the number column.)
FkEmployee #2 = 2002 (which is not what I want, because that year it was the rate that changed and there is a duplicate number) What I want is 2001.
The code I have right now (2015-08-10 14:15)
SELECT t1.FkEmployee, t1.Date
FROM EmployeeRates t1
INNER JOIN
(
SELECT FkEmployee, MAX(Date) AS MaxDate
FROM EmployeeRates
GROUP BY FkEmployee
)
t2 ON t1.FkEmploye = t2.FkEmploye
AND t1.DateTaux = t2.MaxDate
ORDER BY t1.FkEmploye
Thanks for anybody that can help =)
This should work. First find MIN date by Employee, Number, then get the MAX of that. This will ensure you are getting the earliest date per number, but latest date per employee:
SELECT t1.FkEmployee, t1.Date
FROM EmployeeRates t1
INNER JOIN
(SELECT FkEmployee,MAX(MinDate) AS MaxDate from
(SELECT FkEmployee, MIN(Date) AS MinDate
FROM EmployeeRates
GROUP BY FkEmployee,Number) a
GROUP BY Fkemployee
)
t2 ON t1.FkEmployee = t2.FkEmployee
AND t1.DateTaux = t2.MaxDate
ORDER BY t1.FkEmployee
I have table booking in which I have data
GUEST_NO HOTEL_NO DATE_FROM DATE_TO ROOM_NO
1 1 2015-05-07 2015-05-08 103
1 1 2015-05-11 2015-05-12 104
1 1 2015-05-14 2015-05-15 103
1 1 2015-05-17 2015-05-20 101
2 2 2015-05-01 2015-05-02 204
2 2 2015-05-04 2015-05-05 203
2 2 2015-05-17 2015-05-22 202
What I want is to get the result as.
1 ) It should show output as Guest_no, Hotel_no, Room_no, and column with count as number of time previous three column combination repeated.
So OutPut should like
GUEST_NO HOTEL_NO ROOM_NO Count
1 1 103 2
1 1 104 1
1 1 101 1
2 2 204 1
etc. But I want result to in ordered way e.g.: The output should be order by bk.date_to desc
My query is as below its showing me count but if I use order by its not working
select bk.guest_no, bk.hotel_no, bk.room_no,
count(bk.guest_no+bk.hotel_no+bk.room_no) as noOfTimesRoomBooked
from booking bk
group by bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to
order by bk.date_to desc
So with adding order by result is showing different , because as I added order by date_to column so i have to add this column is group by clause too which will end up in different result as below
GUEST_NO HOTEL_NO ROOM_NO Count
1 1 103 1
1 1 104 1
1 1 103 1
1 1 101 1
2 2 204 1
Which is not the output I want.
I want these four column but with order by desc of date_to column and count as no of repetition of first 3 columns
I think a good way to do this would be grouping by guest_no, hotel_no and room_no, and sorting by the maximum (i.e. most recent) booking date in each group.
SELECT
guest_no,
hotel_no,
room_no,
COUNT(1) AS BookingCount
FROM
booking
GROUP BY
guest_no,
hotel_no,
room_no
ORDER BY
MAX(date_to) DESC;
Maybe this is what you're looking for?
select
guest_no,
hotel_no,
room_no,
count(*) as Count
from
booking
group by
guest_no,
hotel_no,
room_no
order by
min(date_to) desc
Or maybe max() instead of min(). SQL Fiddle: http://sqlfiddle.com/#!6/e684c/3
You could try this.
select t.* from
(
select bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to,
count(*) as noOfTimesBooked from booking bk
group by bk.guest_no, bk.hotel_no, bk.room_no, bk.date_to
) t
order by t.date_to
You will also have to select date_to and then group the result by it.
If you use 'group by' clause, SQL Server doesn't allow you to use 'order by'. So you can make a sub query and use 'order by' in the outer query.
SELECT * FROM
(select bk.guest_no,bk.hotel_no,bk.room_no
,count(bk.guest_no+bk.hotel_no+bk.room_no) as noOfTimesRoomBooked,
(SELECT MAX(date_to) FROM booking CK
WHERE CK.guest_no=BK.guest_no AND bk.hotel_no=CK.bk.hotel_no
bk.room_no=CK.ROOM_NO ) AS DATEBOOK
from booking bk
group by bk.guest_no,bk.hotel_no,bk.room_no,bk.date_to) A
ORDER BY DATEBOOK
IT MIGHT HELP YOU
This is to understand how long it took the customer to pay a bill.
The datediff needs to be the next invoice to the payments
as Below example
ID Type1 Amount Date
--------------------------------------------------------------------
1 Invoice 38.16 2014-04-25
1 Payment -40.00 2014-03-23
1 Invoice 40.86 2014-02-22
1 Payment -40.00 2014-02-21
1 Invoice 42.21 2014-01-20
ID Type1 Amount Date DATEDIFF
---------------------------------------------------------
1 Invoice 38.16 2014-04-25
1 Payment -40.00 2014-03-23 29
1 Invoice 40.86 2014-02-22
1 Payment -40.00 2014-02-21 32
1 Invoice 42.21 2014-01-20
This can be done in many ways, one option is to use a correlated sub-query to get the date of the preceding row with item=invoice for all item=payment rows:
select
id, type1, amount, date,
datediff(day,
(select top 1 date
from table1
where date <= t.date
and type1= 'Invoice'
and t.type1='Payment'
order by date desc),
date) as diff
from table1 t;
This might not be the most efficient solution though.
Sample SQL Fiddle
Or you could use an outer apply with the same effect: http://www.sqlfiddle.com/#!6/b1e32/19
My table looks something like this:
group date cash checks
1 1/1/2013 0 0
2 1/1/2013 0 800
1 1/3/2013 0 700
3 1/1/2013 0 600
1 1/2/2013 0 400
3 1/5/2013 0 200
-- Do not need cash just demonstrating that table has more information in it
I want to get the each unique group where date is max and checks is greater than 0. So the return would look something like:
group date checks
2 1/1/2013 800
1 1/3/2013 700
3 1/5/2013 200
attempted code:
SELECT group,MAX(date),checks
FROM table
WHERE checks>0
GROUP BY group
ORDER BY group DESC
problem with that though is it gives me all the dates and checks rather than just the max date row.
using ms sql server 2005
SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group
That works to get the max date..join it back to your data to get the other columns:
Select group,max_date,checks
from table t
inner join
(SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group)a
on a.group = t.group and a.max_date = date
Inner join functions as the filter to get the max record only.
FYI, your column names are horrid, don't use reserved words for columns (group, date, table).
You can use a window MAX() like this:
SELECT
*,
max_date = MAX(date) OVER (PARTITION BY group)
FROM table
to get max dates per group alongside other data:
group date cash checks max_date
----- -------- ---- ------ --------
1 1/1/2013 0 0 1/3/2013
2 1/1/2013 0 800 1/1/2013
1 1/3/2013 0 700 1/3/2013
3 1/1/2013 0 600 1/5/2013
1 1/2/2013 0 400 1/3/2013
3 1/5/2013 0 200 1/5/2013
Using the above output as a derived table, you can then get only rows where date matches max_date:
SELECT
group,
date,
checks
FROM (
SELECT
*,
max_date = MAX(date) OVER (PARTITION BY group)
FROM table
) AS s
WHERE date = max_date
;
to get the desired result.
Basically, this is similar to #Twelfth's suggestion but avoids a join and may thus be more efficient.
You can try the method at SQL Fiddle.
Using an in can have a performance impact. Joining two subqueries will not have the same performance impact and can be accomplished like this:
SELECT *
FROM (SELECT msisdn
,callid
,Change_color
,play_file_name
,date_played
FROM insert_log
WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
ORDER BY callid ASC) t1
JOIN (SELECT MAX(date_played) AS date_played
FROM insert_log GROUP BY callid) t2
ON t1.date_played = t2.date_played
SELECT distinct
group,
max_date = MAX(date) OVER (PARTITION BY group), checks
FROM table
Should work.