How to get multiple rows based on max date - sql

I have a table SalePrices in SQL server and data same as below:
SPID ProductID Price Date
001 Pro01 10 2016-03-10
002 Pro01 20 2016-03-11
003 Pro02 10 2016-03-13
004 Pro02 20 2016-03-15
What I want is create a view that show only one ProductID and Price that I have modified at the last time. So what I want is same as the result below:
ProductID Price Date
Pro01 20 2016-03-11
Pro02 20 2016-03-15

There're few different approaches for this, for example, using row_number():
;with cte as (
select
ProductID, Price, Date,
row_number() over(partition by ProductID order by Date desc) as rn
from <Table>
)
select
ProductID, Price, Date
from cte
where
rn = 1
sql fiddle demo

Another version with windowing functions, this one with FIRST_VALUE();
SELECT ProductID, price, date
FROM products
WHERE spid IN (
SELECT FIRST_VALUE(spid) OVER (PARTITION BY ProductID ORDER BY date DESC) spid
FROM products
)
An SQLfiddle to test with.
Note that Roman's version with ROW_NUMBER should work from SQL Server 2005 and newer, while this will only work for SQL Server 2012 and newer.

TRY THIS:
SELECT
ProductID
, Price
, Date FROM tablename AS A
JOIN (SELECT ProductID,MAX(Date) AS DATE FROM tablename
GROUP BY ProductID
) AS B ON A.Date=B.DATE AND A.ProductID=B.ProductID

one more approach...
select productid,price,date
from
table t1
where date=(select max(date) from table t2 where t1.productid=t2.productid)

Your last record will have the highest SPID:
select
ProductId, Price, Date
from
SalePrices sap
where
sap.spid =(
select
max(sap2.spid)
from
SalePrices sap2
where
sap2.productId = sap.productId)
This query will give u desired result:
ProductID Price Date
Pro01 20 2016-03-11
Pro02 20 2016-03-15

Related

How to calculate +ve and -ve amounts on Totals in SQL?

The below Product table, Product ID - 100 as duplicated twice, and also there are negative profits are needs to Substract while calculating the Profit wise Total.
PID | Pname | Profit
100 AB 20
100 AB 20
101 BC 30
102 CD -10
103 DE -10
Expected Result: 30
Please provide the SQL query to get this result. Thanks in advance!!!
Is this what you want?
select sum(profit)
from (select distinct t.*
from t
) t
WITH CTE AS (
SELECT ROW_NUMBER() OVER (PARTITION BY PID ORDER BY PID ) AS rn,
PID,Pname,Profit FROM TableName
)
SELECT CAST(SUM(Profit) AS INT) AS Profit FROM CTE
WHERE rn=1
Note:- First you to get the DISTINCT Record then..use sum function...

Firebird Query- Return first row each group

In a firebird database with a table "Sales", I need to select the first sale of all customers. See below a sample that show the table and desired result of query.
---------------------------------------
SALES
---------------------------------------
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
3 25 05/04/16 08:10
4 31 07/03/16 10:22
5 22 01/02/16 12:30
6 22 10/01/16 08:45
Result: only first sale, based on sale date.
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
4 31 07/03/16 10:22
6 22 10/01/16 08:45
I've already tested following code "Select first row in each GROUP BY group?", but it did not work.
In Firebird 2.5 you can do this with the following query; this is a minor modification of the second part of the accepted answer of the question you linked to tailored to your schema and requirements:
select x.id,
x.customerid,
x.dthrsale
from sales x
join (select customerid,
min(dthrsale) as first_sale
from sales
group by customerid) p on p.customerid = x.customerid
and p.first_sale = x.dthrsale
order by x.id
The order by is not necessary, I just added it to make it give the order as shown in your question.
With Firebird 3 you can use the window function ROW_NUMBER which is also described in the linked answer. The linked answer incorrectly said the first solution would work on Firebird 2.1 and higher. I have now edited it.
Search for the sales with no earlier sales:
SELECT S1.*
FROM SALES S1
LEFT JOIN SALES S2 ON S2.CUSTOMERID = S1.CUSTOMERID AND S2.DTHRSALE < S1.DTHRSALE
WHERE S2.ID IS NULL
Define an index over (customerid, dthrsale) to make it fast.
in Firebird 3 , get first row foreach customer by min sales_date :
SELECT id, customer_id, total, sales_date
FROM (
SELECT id, customer_id, total, sales_date
, row_number() OVER(PARTITION BY customer_id ORDER BY sales_date ASC ) AS rn
FROM SALES
) sub
WHERE rn = 1;
İf you want to get other related columns, This is where your self-answer fails.
select customer_id , min(sales_date)
, id, total --what about other colums
from SALES
group by customer_id
So simple as:
select CUSTOMERID min(DTHRSALE) from SALES group by CUSTOMERID

Querying table with group by and sum

I have the following table called Orders
Order | Date | Total
------------------------------------
34564 | 03/05/2015| 15.00
77456 | 01/01/2001| 3.00
25252 | 02/02/2008| 4.00
34564 | 03/04/2015| 7.00
I am trying to select the distinct order sum the total and group by order #, the problem is that it shows two records for 34564 because they are different dates.. How can I sum if they are repeated orders and pick only the max(date) - But sill sum the total of the two instances?
I.E result
Order | Date | Total
------------------------------------
34564 | 03/05/2015| 22.00
77456 | 01/01/2001| 3.00
25252 | 02/02/2008| 4.00
Tried:
SELECT DISTINCT Order, Date, SUM(Total)
FROM Orders
GROUP BY Order, Date
Of couse the above won't work as you can see but i am not sure how to achieve what i intend.
SELECT [order], MAX(date) AS date, SUM(total) AS total
FROM Orders o
GROUP BY [order]
You can use the MAX aggregate function to choose the latest Date to appear from each Order group:
SELECT Order, MAX(Date) AS Date, SUM(Total) AS Total
FROM Orders
GROUP BY Order
Simplest query should be:
SELECT MAX(Order), MAX(Date), SUM(Total)
FROM Orders
You can use SUM and MAX together:
SELECT
[Order],
[Date] = MAX([Date]),
Total = SUM(Total)
FROM tbl
GROUP BY [Order]
A word of advice, please refrain from using reserved words like Order and Date for your columns and table names.
Just add MAX(Date) to your SELECT clause.
Try this :
SELECT DISTINCT Order, MAX(Date), SUM(Total)
FROM Orders
GROUP BY Order, Date

Get max of column using sum

I have one table with following data..
saleId amount date
-------------------------
1 2000 10/10/2012
2 3000 12/10/2012
3 2000 11/12/2012
2 3000 12/10/2012
1 4000 11/10/2012
4 6000 10/10/2012
From my table I want result with max of sum amount between dates 10/10/2012 and 12/10/2012 which for the data above will be:
saleId amount
---------------
1 6000
2 6000
4 6000
Here 6000 is the max of the sums (by saleId) so I want ids 1, 2 and 4.
You have to use Sub-queries like this:
SELECT saleId , SUM(amount) AS Amount
FROM Table1
GROUP BY saleId
HAVING SUM(amount) =
(
SELECT MAX(AMOUNT) FROM
(
SELECT SUM(amount) AS AMOUNT FROM Table1
WHERE date BETWEEN '10/10/2012' AND '12/10/2012'
GROUP BY saleId
) AS A
)
See this SQLFiddle
This query goes through the table only once and is fairly optimised.
select top(1) with ties saleid, amount
from (
select saleid, sum(amount) amount
from tbl
where date between '20121010' and '20121210'
group by saleid
) x
order by amount desc;
You can produce the SUM with the WHERE clause as a derived table, then SELECT TOP(1) in the query using WITH TIES to show all the ones with the same (MAX) amount.
When presenting dates to SQL Server, try to always use the format YYYYMMDD for robustness.

Find out the Old Date from a date column in sql

How the find the oldest values from the datetime column?
I have table with datetime column (UpdateDate), and i need to find out the oldest data based on the UpdateDate .
Id UpdateDate Desc
-----------------------------------------
1 2010-06-15 00:00:00.000 aaaaa
2 2009-03-22 00:00:00.000 bbbbb
3 2008-01-12 00:00:00.000 ccccc
4 2008-02-12 00:00:00.000 ddddd
5 2009-04-03 00:00:00.000 eeeee
6 2010-06-12 00:00:00.000 fffff
I have Find out the old year dates from the current date using
Select UpdateDate from Table1 where DATEDIFF(YEAR,UpdateDate,getdate()) > 0 Query. But I need to find out the 2008th data only (Since the 2008 is the oldest one here)
I dont know what is there in the Table I need find out the Oldest date values.. How is it Possible?
Select UpdateDate from Table1 where DATEDIFF(YEAR,PartDateCol,getdate()) IN
(Select MAX(DATEDIFF(YEAR,PartDateCol,GETDATE())) DiffYear from Table1)
This will return two record of 2008. If your records has four 2006 date than it return all 2006 data if difference is large.
One way of doing this is
Select UpdateDate from Table1 where YEAR(UpdateDate )=2008
But, you can find out the oldest dates by ordering the data as such
Select * from Table1 order by UpdateDate ASC
You can use top and order by.
select top(1) UpdateDate
from Table1
order by UpdateDate
Update:
If you want all rows for the first year present you can use this instead.
select *
from (
select *,
rank() over(order by year(UpdateDate)) as rn
from Table1
) as T
where T.rn = 1
If you want the data that within 2008 year try this:
Select UpdateDate From Table1
Where Year(UpdateDate) =
(
Select Year(UpdateDate)
from Table1 Order By UpdateDate ASC Limit 1
) ;