SQL where in sql subquery with order by - sql

This is my query
SELECT * FROM Place WHERE Place.Id IN (
SELECT TOP 10 PlaceId from #ResultPlaceList order by CPlaceId desc)
my result is ordered by Place.ID, but i want to have a result with ordered CPlaceId.

You could use a join to use the cPlaceId column for ordering:
select p.*
from Place p
join (
select top 10 PlaceId,
CPlaceId
from #ResultPlaceList
order by CPlaceId desc
) r on p.Id = r.PlaceId
order by r.CPlaceId;

You will have to do a JOIN to accomplish this. It will look something like this:
SELECT TOP 10 Place.*
FROM Place
JOIN #ResultPlaceList ON #ResultPlaceList.PlaceId = Place.Id
ORDER BY CPlaceId DESC

Something like this....
SELECT * FROM PLACE WHERE PLACE.ID IN (
SELECT PLACEID
FROM (
SELECT PLACEID
, ROW_NUMBER() OVER (ORDER BY CPLACEID DESC) RNUM
FROM #RESULTPLACELIST
) TMP
WHERE RNUM <= 10
)

'SELECT C.ID
FROM CustomerDetails C
LEFT JOIN UserInfo U ON C.ID = U.ID
Order by U.ID'
Can you modify your query like this

Related

How to group/aggregate rows in a table based on values in a column

I have a table of chats between buyers and sellers, and in many cases there are chats between the same buyer and a seller (with different chatids), that have different lastactivity dates (shown here in Unix time).
My goal is to be able to query this table so that only a single chatid is returned for each buyer/seller pair, and this chatid corresponds to whichever chat had the most recent lastactivity - so like this:
I've tried:
SELECT max(lastactivity), chatid, buyerid, supplierid,
FROM chat_table
GROUP BY 2,3,4
but this doesn't seem to work...
Anyone able to help?
In Redshift, I would do use window functions:
select ct.*
from (select ct.*,
row_number() over (partition by least(buyerid, supplierid), greatest(buyerid, supplierid)
order by lastactivity
) as seqnum
from chat_table ct
) ct
where seqnum = 1;
Using a simpler approach, using self-JOIN,
SELECT a.buyerid, a.sellerid, a.chatid, a.lastactivity
FROM chat_table a
JOIN (SELECT MAX(lastactivity),buyerid, sellerid FROM chat_table GROUP BY buyerid, sellerid) b
ON a.buyerid = b.buyerid
AND a.sellerid = b.sellerid
AND a.lastactivity = b.lastactivity ;
With NOT EXISTS:
SELECT c.*
FROM chat_table c
WHERE NOT EXISTS (
SELECT 1 FROM chat_table
WHERE buyerid = c.buyerid AND supplierid = c.supplierid AND lastactivity > c.lastactivity
)
select a.lastactivity, a.buyerid, a.supplierid, a.chatid
from (SELECT max(lastactivity) lastactivity, buyerid, supplierid
FROM chat_table
GROUP BY 2,3) a
left join chat_table b on a.buyerid=b.buyerid and a.supplierid=b.supplierid and a.lastactivity=b.kastactivity;
You need to use window function like row_number.
The partition will be the buyer_id and seller_id,
order by the lastactivity.
In the outer query filter the rows where rownumber=1.
https://docs.aws.amazon.com/redshift/latest/dg/c_Window_functions.html
As this question is tagged to aws-redshift. Below query works. Try this.
Select *from chat_table
where (buyerid,sellerid, lastactivity)
IN(
Select buyerid,sellerid, max(lastactivity) as lastactivity
from chat_table
Group by buyerid,sellerid);

How can I get latest comment from specific new?

I have a table
News(newsId, text, date)
and
Comments(commentId, text, date, newsId)
and I need to select 10 newest news by date with a newest comment from each. So far I have this, how do I improve it and finish it?
SELECT date,
newsId,
commentid,
date
FROM News,
comments
ORDER BY date DESC
LIMIT 10;
You can do this using row_number() as:
select n.newsid, n.text, n.text, n.date, c.text as comment
from news n left join
(select c.*,
row_number() over (partition by c.newsid order by date desc) as seqnum
from comments c
) c
on c.newsId = n.newsId and seqnum = 1
order by n.date desc
limit 10;
Note that this returns news items with no comments. If you do not want those, then change the left join to an inner join.
if your dbms support row_number then you can try like below
with cte as
(select *,row_number()over(partition by newsId order by date desc) rn
from News
), cte1 as
(
select newsId, text, date from cte where rn<=10
) select cte1.*,c.commentId,c.text as commnt from cte1 join Comments c on cte1.newsid=c.newsid
For older DBMS subquery will useful :
select n.newsid, n.text, n.text, n.date, c.text as comment
from news n inner join
comments c
on c.newsId = n.newsId
where c.date in (select c1.date
from comments c1
where c1.newsid = n.newsid
order by c1.date desc
limit 10
);
Howver, for newest version DBMS row_number() is a generic to do this.

Limiting SQL Result

I have a query where I am trying to get results from a table:
SELECT P.P_CODE, P.P_JEWELRYTYPE,P.p_catalog, P_AVAILABLE, P_RESERVED , p.p_catalog
FROM products P
WHERE
P.p_catalog IN (8796093383256,8796093252184,8796093317720,8796093121112,8796093186648);
I want a query where I can limit the number of results to 500 of each catalog type. How should I modify my query to achieve this?
Analytical function row_number() will work which will assign row numbers to each p_catalog so that you could filter on that condition in WHERE clause in an outer query:
SELECT *
FROM (
SELECT
p.P_CODE, p.P_JEWELRYTYPE, p.p_catalog, p.P_AVAILABLE, p.P_RESERVED, p.p_catalog,
row_number() over (partition by p.p_catalog) as rn
FROM products p
WHERE p.p_catalog IN (8796093383256,8796093252184,8796093317720,8796093121112,8796093186648)
) p
WHERE rn <= 500;
Use row_number():
select p.*
from (select p.*, row_number() over (partition by catalog order by null) as seqnum
from products p
) p
where p.seqnum <= 500;
You can put the where filtering in either the inner or outer query.

How can I fix my GROUP BY clause

I have 2 tables as seen below:
Now the question is :
How can I have a view which shows the details of the last Owner? in other words I need the details of person who has MAX(StartDate) in tbl_Owners table?
I want to find the latest owner of each apartment.
I tried different approaches but I couldn't find the way to do that.
I know I need to get the personID in a Group By clause which groups records by AppID but I can't do that
Thank you
Try this
select t1.* from tbl_persons as t1 inner join
(
select t1.* from tbl_owners as t1 inner join
(
select appid,max(startdate) as startdate from tbl_owners group by appid
) as t2
on t1.appid=t2.appid and t1.startdate=t2.startdate
) as t2
on t1.personid=t2.personid
Add this to your query:
JOIN (select AppId, MAX(StartDate) as MAxStartDate
from dbo.tbl_Owners
group by PersonId) o2
ON dbo.tbl_Owners.AppId= o2.AppId and
dbo.tbl_Owners.StartDate = o2.MAxStartDate
The sub-query above returns every AppId together with it's latest StartDate. Self-joining with that result will give you what you want.
You can USE CTE for this purpose
;WITH CTE AS
(
SELECT AppID,PersonID,StartDate,
ROW_NUMBER() OVER (PARTITION BY AppID ORDER BY StartDate DESC) RN
FROM TableNAme
GROUP BY AppID,PersonID,StartDate
)
SELECT * FROM CTE
WHERE RN=1
Using row_number
select t.*, p.* -- change as needed
from (select *, rn= row_number() over(partition by AppID order by StartDate desc)
from dbo.tbl_Owners
) t
join dbo.tbl_Persons p on t.rn=1 and t.PersonId = p.PersonId
using cross apply
select t.*, p.* -- change as needed
from dbo.tbl_Persons p
cross apply (
select top(1) *
from dbo.tbl_Owners o
where o.PersonId = p.PersonId
order by o.StartDate desc
) t
SELECT dbo.tbl_Owners.*,dbo.tbl_Persons.PersonFullname FROM dbo.tbl_Owners
INNER JOIN
dbo.tbl_Persons ON dbo.tbl_Owners.PersonID=dbo.tbl_Persons.PersonID
GROUP BY dbo.tbl_Owners.StartDate HAVING MAX(StartDate);
Use GROUP BY on StartDate instead on PersonID.

Highest Count with a group

I'm having an absolute brain fade
SELECT p.ProductCategory, f.ProductSubCategory, COUNT(*) AS Cnt
FROM Sales f
JOIN Products p ON f.ProductSubCategory = p.ProductSubCategory
GROUP BY p.ProductCategory, f.ProductSubCategory
ORDER BY 1,3 DESC
This shows me the count for each ProductSubCategory, I would like to see only the highest ProductSubCategory per ProductCategory.
I wish to see (I don't care about the Count value)
There are a couple of different ways to do this. One involves joining the results back to themselves and using the max aggregate. But since you are using SQL Server, you can use ROW_NUMBER to achieve the same result:
with cte as (
select p.productcategory, p.ProductSubCategory, COUNT(*) cnt,
ROW_NUMBER() over (partition by p.productcategory order by count(*) desc) rn
from products p
join sales s on p.ProductSubCategory = s.ProductSubCategory
group by p.productcategory, p.ProductSubCategory
)
select *
from cte
where rn = 1
You already got the answer, Please see the following code to. It may help you.
SELECT p.ProductCategory,
f.ProductSubCategory,
COUNT(*) AS Cnt
FROM Sales f
JOIN Products p ON f.ProductSubCategory = p.ProductSubCategory
JOIN (
SELECT p.ProductCategory,
f.ProductSubCategory,
ROW_NUMBER() OVER ( PARTITION BY p.ProductCategory,
f.ProductSubCategory
ORDER BY COUNT(*) DESC) [Row]
FROM Sales f
JOIN Products p ON f.ProductSubCategory = p.ProductSubCategory) Lu
ON P.ProductCategory = Lu.ProductCategory
AND f.ProductSubCategory = Lu.ProductSubCategory
WHERE Lu.Row = 1
GROUP By p.ProductCategory,
f.ProductSubCategory