Sql select newest date - sql

I am trying to make a view with the following code...
SELECT DISTINCT
TOP (100) PERCENT .dbo.InventoryItems.ItemNo, .dbo.InventoryItems.ItemID, .dbo.InventoryItems.DescriptionMed,
.dbo.PODetails.MostRecentCost, .dbo.UOMs.UOMCode, .dbo.PODetails.BuyUOMID, .dbo.UOMConvert.Factor,
.dbo.PODetails.MostRecentCost * .dbo.UOMConvert.Factor AS [Price Test], .dbo.PO.EntryDate,
.dbo.UOMConvert.UOMID
FROM .dbo.PO INNER JOIN
.dbo.PODetails ON .dbo.PO.POID = .dbo.PODetails.POID INNER JOIN
.dbo.UOMConvert INNER JOIN
.dbo.UOMs ON .dbo.UOMConvert.ToUOMID = .dbo.UOMs.UOMID INNER JOIN
.dbo.InventoryItems ON .dbo.UOMConvert.ItemID = .dbo.InventoryItems.ItemID ON
.dbo.PODetails.ItemNo = .dbo.InventoryItems.ItemNo
ORDER BY .dbo.PO.EntryDate DESC
that gives me all records sorted by the Entrydate but I am only looking to keep the newest record for each ItemNo. I have tried adding group by statements, row numbers and a MAX() statement but I must be entering all of them in wrong as they are all giving me errors due to my limited knowledge of SQL. :( Any help would be greatly appreciated.
Thanks!

use window function.
select * from (
select row_number()over(partition by itemno order by Entrydate desc) Rn,
....
from table1 join ...)
A where rn=1

Related

Can we use order by in subquery? If not why sometime could use top(n) order by?

I'm an entry level trying to learn more about SQL,
I have a question "can we use order by in subquery?" I did look for some article says no we could not use.
But on the other hand, I saw examples using top(n) with order by in subquery:
select c.CustomerId,
c.OrderId
from CustomerOrder c
inner join (
select top 2
with TIES CustomerId,
COUNT(distinct OrderId) as Count
from CustomerOrder
group by CustomerId
order by Count desc
) b on c.CustomerId = b.CustomerId
So now I'm bit confused.
Could anyone advise?
Thank you very much.
Yes, you are right we cannot use order by in a inner query. Because it is acting as a table. A table in itself needs to be sorted when queried for different purposes.
In your query itself the inner query is select some records using Top 2. Eventhough these are top 2 records only, they form a table with 2 records which is enough for it to recognized as a table and join it with another table
The right query will be:-
SELECT * FROM
(
SELECT c.CustomerId, c.OrderId, DENSE_RANK() OVER(ORDER BY b.count DESC) AS RANK
FROM CustomerOrder c
INNER JOIN
(SELECT CustomerId, COUNT(distinct OrderId) as Count
FROM CustomerOrder GROUP BY CustomerId) b
ON c.CustomerId = b.CustomerId
) a
WHERE RANK IN (1,2);
Hope I have answered your question.
Yes we can use order by clause in sub query, for example i have a table named as product (check the screen shot of table http://prntscr.com/f15j3z). Chek this query on your side and revert me in case of any doubt.
select p1.* from product as p1 where product_id = (select p2.product_id from product as p2 order by product_id limit 0,1)
yes we can use order by in subquery,but it is pointless to use it.
It is better to use it in the outer query.There is no use of ordering the result of subquery, because result of inner query will become the input for outer query and it does not have to do any thing with the order of the result of subquery.

Sub query in a inner join

Well, in order to get the last entry by date i've done that query :
select cle
from ( select cle, clepersonnel, datedebut, row_number()
over(partition by clepersonnel order by datedebut desc) as rn
from periodeoccupation) as T
where rn = 1
This one is working and give me the last entry by date, so far i'm ok.
But its the first time i work with subquery and i have to make my query way more complex with multiple joins. But i cannot figure out how to make a subquery in a inner join.
This is what i try :
select personnel.prenom, personnel.nom
from personnel
inner join
( select cle, clepersonnel, datedebut, row_number()
over(partition by clepersonnel order by datedebut desc) as rn
from periodeoccupation) as T
ON personnel.cle = periodeoccupation.clepersonnel
where rn = 1
but its not working !
If you have any idea or tips...Thank you !
Simply change
ON personnel.cle = periodeoccupation.clepersonnel
to
ON personnel.cle = T.clepersonnel
The query join has been aliased with T and you have reference the alias as the table in the aliased query is out of scope in your outer statement.

How to group my table for latest date and ID?

I have a table like this:
I need group this table latest date for every ID.
I mean, I want to get last row every ID. Here is my query:
SELECT DISTINCT ch.Date,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, [Date] from tblCommonHistory ) ch
ON ch.TableIDentity = rk.ID order by ID
How can I do what I want?
EDIT: This query worked for me:
SELECT DISTINCT ch.dt,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, max([Date]) as dt from tblCommonHistory group by TableIdentity) ch ON ch.TableIDentity = rk.ID order by ID
Just use aggregation:
select TableIdentity, max([date])
from tblCommonHistory
group by TableIdentity;
Your question only mentions one table. Your query has two; I don't understand the discrepancy.
It's strange that you have duplicated TableIdentity in tblCommonHistory, but otherwise you should not be getting multiple dates for the same ID from your query.
And also, the only reason to join the 2 tables seems to be that you need to skip those ID that are not present in the tblrisk (is it what you need to do?)
In that case, I'd suggest
SELECT max(ch.Date) AS [Date],ID FROM dbo.tblrisk AS rk
inner join tblCommonHistory AS ch ON ch.TableIDentity = rk.ID
group by ID order by ID

Getting most recent records using the MAX function and Subquery taking very long and almost impossible to query

I am trying to get the most recent record for each user as highlighted in the screenshot below:
SELECT *
FROM RENTAL
WHERE LastVisit =
(SELECT Max(T.LastVisit)
FROM RENTAL AS T
WHERE T.UserID = RENTAL.UserID)
The problem is it takes extremely very long time to get results.
Is there a faster alternative way?
Create a GROUP BY query which gives you the most recent LastVist for each UserID.
SELECT
T.UserID,
Max(T.LastVisit) AS MaxOfLastVisit
FROM RENTAL AS T
GROUP BY T.UserID;
If that was correct, use it as a subquery which you join back to RENTAL. The outcome should be filtering RENTAL to only those rows which match the subquery rows.
SELECT R.*
FROM
RENTAL AS R
INNER JOIN
(
SELECT
T.UserID,
Max(T.LastVisit) AS MaxOfLastVisit
FROM RENTAL AS T
GROUP BY T.UserID
) AS sub
ON
r.UserID = sub.UserID
AND r.LastVist = sub.MaxOfLastVisit;
Use this query
SELECT * FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY LastVisit DESC) rnk,*
FROM RENTAL
)a
WHERE a.rnk=1

Distinct on multi-columns in sql

I have this query in sql
select cartlines.id,cartlines.pageId,cartlines.quantity,cartlines.price
from orders
INNER JOIN
cartlines on(cartlines.orderId=orders.id)where userId=5
I want to get rows distinct by pageid ,so in the end I will not have rows with same pageid more then once(duplicate)
any Ideas
Thanks
Baaroz
Going by what you're expecting in the output and your comment that says "...if there rows in output that contain same pageid only one will be shown...," it sounds like you're trying to get the top record for each page ID. This can be achieved with ROW_NUMBER() and PARTITION BY:
SELECT *
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY c.pageId ORDER BY c.pageID) rowNumber,
c.id,
c.pageId,
c.quantity,
c.price
FROM orders o
INNER JOIN cartlines c ON c.orderId = o.id
WHERE userId = 5
) a
WHERE a.rowNumber = 1
You can also use ROW_NUMBER() OVER(PARTITION BY ... along with TOP 1 WITH TIES, but it runs a little slower (despite being WAY cleaner):
SELECT TOP 1 WITH TIES c.id, c.pageId, c.quantity, c.price
FROM orders o
INNER JOIN cartlines c ON c.orderId = o.id
WHERE userId = 5
ORDER BY ROW_NUMBER() OVER(PARTITION BY c.pageId ORDER BY c.pageID)
If you wish to remove rows with all columns duplicated this is solved by simply adding a distinct in your query.
select distinct cartlines.id,cartlines.pageId,cartlines.quantity,cartlines.price
from orders
INNER JOIN
cartlines on(cartlines.orderId=orders.id)where userId=5
If however, this makes no difference, it means the other columns have different values, so the combinations of column values creates distinct (unique) rows.
As Michael Berkowski stated in comments:
DISTINCT - does operate over all columns in the SELECT list, so we
need to understand your special case better.
In the case that simply adding distinct does not cover you, you need to also remove the columns that are different from row to row, or use aggregate functions to get aggregate values per cartlines.
Example - total quantity per distinct pageId:
select distinct cartlines.id,cartlines.pageId, sum(cartlines.quantity)
from orders
INNER JOIN
cartlines on(cartlines.orderId=orders.id)where userId=5
If this is still not what you wish, you need to give us data and specify better what it is you want.