Solved

How to use TOP 1 in a T-SQL sub-query?

Posted on 2016-10-25
14
31 Views
Last Modified: 2016-10-26
Can someone help me with the correct syntax for a T-SQL query I am trying to apply in a SQL Server 2005 database?

I have TABLE_A that contains unique Order Items and a View VW_B that might contain multipe instances of items from TABLE_A along with further columns concerning the Invoices these Order Items might have appeared on.

I would like to create a query that selects each item from TABLE_A and details of only a single instance of them from VW_B (the latest Invoiced they featured on).

I have been trying suggestions from other web-sites but either get syntax errors or only a single row of output.

My latest attempt has been along the lines of :

SELECT A.Col1, A.Col2, B.*
FROM TABLE_A AS A
OUTER APPLY
(SELECT TOP 1 VB.INVREF, VB.INVDATE
 FROM VW_B AS VB
 ORDER BY VB.INVDATE DESC
 WHERE VB.ITEMID = A.ITEMID) AS B

The above format produces a syntax error with the keyword "WHERE" on Line 7.

Is it because I am using a View rather than a Table in my "SELECT TOP 1 ... " sub-query?

I hope someone can understand what I am trying to do and show me where I am going wrong.

Thanks & regards.
Colin.
0
Comment
Question by:colinasad
  • 6
  • 3
  • 3
  • +1
14 Comments
 
LVL 19

Expert Comment

by:Daniel Van Der Werken
Comment Utility
I think it's the ORDER BY in the subquery. I've never been able to have an ORDER BY in a subquery. I'm surprised that didn't show up directly as the problem.

Do the ORDER BY after the final query is created. Does that help?
0
 

Author Comment

by:colinasad
Comment Utility
Thanks for the fast response; I'll try that out now.
Also, I think I made a slight mistake when I was paraphrasing my more meaningful table and column names into the simplified format I gave in my example.
I think the WHERE line should have preceded the ORDER BY line in my sub-query.
Regards.
0
 

Author Comment

by:colinasad
Comment Utility
Hello again.
Yes, I am reading elsewhere that "ORDER BY" is not valid in a sub-query.

I am obviously going about this the wrong way because I do need my sub-query (or some other data extraction method) to do some sort of ordering because I want to find the single row from my View that identifies the most recent Invoice that an Item featured in.
I would have thought that my View needed to be sorted into "Item, InvDate DESC" order so that I could then pick the "TOP 1" row for each of my items to give me their most recent Invoice Date.

Can anyone suggest another strategy rather than my failed sub-query attempts?

Many thanks.
0
 
LVL 19

Expert Comment

by:Daniel Van Der Werken
Comment Utility
Yes, you are correct about the WHERE and ORDER BY locations. Still, take it out of the subquery 'cause I've never been able to get away with that in my own queries.

I see you're doing the top 1 and then ordering by date and hence that's why you want the order by. You can do a similar thing by selecting the max date.

So, do this:

SELECT A.Col1, A.Col2, B.*
FROM TABLE_A AS A
OUTER APPLY
(
   SELECT 
                  VB.INVREF, 
                  VB.INVDATE
 FROM VW_B AS VB
 WHERE VB.ITEMID = A.ITEMID
   AND VB.INVDATE = (SELECT MAX(INVDATE) FROM VW_B WHERE INVREF = VB.INVREF)
) AS B

Open in new window


Anyway, I might not have it exact because I tend to try these things and tweak them to work as I work on them. You should be getting the idea here though. You want yet another subquery that gets the max date from the same table for that item, then use that max date to find the item with the max date.

Therefore, if you have like 10 dates, you get the max data for that ID then get the row with that max date which returns the row you want and is essentially the same as the TOP 1 with order by DESC.
0
 
LVL 19

Expert Comment

by:Daniel Van Der Werken
Comment Utility
Heh. I was typing up the answer to your question as you asked it. If you can think a valid set of data that represents what you have, we can do some test queries.
0
 
LVL 17

Expert Comment

by:Pawan Kumar Khowal
Comment Utility
Try..

SELECT A.Col1, A.Col2, B.*
FROM TABLE_A AS A
OUTER APPLY
(SELECT TOP 1 VB.INVREF, VB.INVDATE
 FROM VW_B AS VB
 WHERE VB.ITEMID = A.ITEMID 
 ORDER BY VB.INVDATE DESC ) AS B

Open in new window

0
 
LVL 26

Expert Comment

by:Zberteoc
Comment Utility
The ORDER BY clause is always the last one in a query. Pawan got it right, here is formatted:
SELECT 
	A.Col1, 
	A.Col2, 
	B.*
FROM 
	TABLE_A AS A
	OUTER APPLY
	(
		SELECT TOP 1 
			VB.INVREF, 
			VB.INVDATE
		FROM 
			VW_B AS VB
		WHERE 
			VB.ITEMID = A.ITEMID
		ORDER BY 
			VB.INVDATE DESC
	) AS B

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:colinasad
Comment Utility
Thanks very much for the further suggestions.
I won't be able to work on this again until tomorrow afternoon (UK time), but I will report back then with my progress.
Best regards.
0
 

Author Comment

by:colinasad
Comment Utility
Thanks for the suggestions, which I have just been able to test before rushing off again.

I have 7,820 items in Table_A
I have on 52 items in View_B

Not all items from Table_A occur in View_B but some if the items in View_B are duplicated because they have recently been invoiced more than once and I only want the most recent instances from View_B.

Daniel's suggestion gives me 7,843 results!
Both Pawan and Zberteoc's suggestions give 7,820 results.

I am hoping to get 52 or fewer results. I only want the items from Table_A that are also generated by View_B.

I might try breaking things down into a couple of separate Views rather than trying to achieve my result in a singe (obviously trick) SQL command.

Any further suggestions welcomed, though.

Best regards. Colin.
0
 
LVL 17

Accepted Solution

by:
Pawan Kumar Khowal earned 500 total points
Comment Utility
try..

CROSS APPLY

SELECT A.Col1, A.Col2, B.*
FROM TABLE_A AS A
CROSS APPLY
(SELECT TOP 1 VB.INVREF, VB.INVDATE
 FROM VW_B AS VB
 WHERE VB.ITEMID = A.ITEMID 
 ORDER BY VB.INVDATE DESC ) AS B

Open in new window

0
 
LVL 26

Expert Comment

by:Zberteoc
Comment Utility
Replace:

OUTER APPLY

with

CROSS APPLY

OUTER APPLY is similar to LEFT JOIN while CROSS APPLY to INNER JOIN.
0
 

Author Closing Comment

by:colinasad
Comment Utility
Thanks for that.
The CROSS APPLY seems to do the job, reducing my results down from 7,820 possible items, through 52 recent invoice events, to the specific 29 items involved in these invoices.
I will double-check that it is producing the correct invoicing event for multi-invoiced items, but I think I now have a mechanism I can work.
I think this is the first time I have used the APPLY feature so will need to read a bit more to get my head around it.
Many thanks to everyone who commented.
0
 
LVL 26

Expert Comment

by:Zberteoc
Comment Utility
Well, for these kind a situation when to the solution more than one expert contributed there is the split points option. :)
0
 

Author Comment

by:colinasad
Comment Utility
Thanks for the further comment, Zberteoc.
It's been a while since I've been on EE and the interface has changed.
In the "old days" you could explicitly split your 500 points across answers.
I'll make use of the "assisted" option in future.
Thanks and regards.
Colin.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This article will describe one method to parse a delimited string into a table of data.   Why would I do that you ask?  Let's say that you need to pass multiple parameters into a stored procedure to search for.  For our sake, we'll say that we wa…
Data architecture is an important aspect in Software as a Service (SaaS) delivery model. This article is a study on the database of a single-tenant application that could be extended to support multiple tenants. The application is web-based develope…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now