SQL Statement for limiting the number of detail retrieved in Access 2000?

  • Thread starter Thread starter Hexman
  • Start date Start date
H

Hexman

Hello All,

How do I limit the number of detail records selected in a Master-Detail set using SQL?

I want to select all master records for a date, but only the first 3 records for the details (based on the primary key of the detail record). I've
been trying with "TOP 3", but can't get anywhere. Using Access 2000.

Something like:

SELECT t1.*, TOP 3 t2.*
FROM t1, t2
WHERE (t1.item = t2.item) AND (t1.TrnDate = #09/23/06#)

Any help appreciated,

Hexman
 
Try this: (Or something of the like)

SELECT t1.*, t3.*
FROM t1
INNER JOIN
(SELECT TOP 3 t2.*
FROM t2) t3 ON t1.Item = t3.Item
WHERE (t1.TrnDate = #09/23/06#)

You may even want too use a LEFT OUTER JOIN for this, depends on your
data.

Izzy
 
Izzy,

Thanks for the response. I still can't get it to work, either with Access or SS EE. It generates no error during execution, but doesn't return any
rows. If I take out the "(SELECT TOP 3 t2.* FROM t2)" and change all "t3" references to "t2", it retrieves the rows (except too many of them).

This has me stumped. Any further ideas?

All I want to do is limit the number of rows returned from t2 to be joined with t1.

Thanks,

Hexman
 
Hexman said:
Hello All,

How do I limit the number of detail records selected in a Master-Detail set using SQL?

I want to select all master records for a date, but only the first 3
records for the details (based on the primary key of the detail record).
I've
been trying with "TOP 3", but can't get anywhere. Using Access 2000.

Something like:

SELECT t1.*, TOP 3 t2.*
FROM t1, t2
WHERE (t1.item = t2.item) AND (t1.TrnDate = #09/23/06#)

Any help appreciated,

Hexman

You need to understand what you're doing before you can optimize it :)
Now you're creating a dataset that effectively creates a copy of all
records in t2 for each entry in t1. If you have alot of records, this
will get ouf of hand very quickly (i.e. 2 tables with 1000 records each
will cause 10.000 records in memory this way) So using a join like Izzy
suggested is usually much better.

How about this:

Select *
from t1 inner join t2 on (t1.item=t2.item)
where t1.TrnDate=#09/23/06#
and t2.item in
(select top 3 item from t2)

This should join the 2 tables where the 'item' in the 2 tables match and
the date in t1 is the one specified and the items appear in the top 3 of
t2. There is no sort order given to t2, so results may be unpredictable.
 
Hi

I don't think you're going to be able to do this as the "Top x" clause
is going to limit your resultset to x number of records, not x number
of records for each 'grouping' (i.e. the link between your two tables)
so no matter how you try to link the results of this subquery to your
master table, you're only ever (at best) going to get x records from
the subquery.

Cheers
Martin
 
Martin is right, this cannot be handled in a query.

This will need to be handled in application code.

The only way this would work in a query is if the only 1 record was
returned by t1.

Izzy
 
Hi Rinze

You're absolutely right - I was trying to think of how to limit the
result set in the detail selection before the join happened and
completely missed the use of IN() along with a subquery. I knew I
should have waiting longer before posting!

As for performance on this - as you say, it sucks! Mainly because, as
far as I understand, it's running the subquery for each and every row
in the resultset.

Having just ran a quick test on a couple of handy tables I have here
(only returning 1500 rows in the end results) and the performance was
way too slow to be acceptable for me so depending on the need I think
I'd probably just do a straight join and then limit the number that I
display client-side (again, depending on the volume of data that's got
to travel the wire and how frequently etc).

Still - at least I can cross "learn something new today" off my TODO
list!

Martin
 
yeah but you could easily do it as a correlated subquery

Orders and OrderDetails, ok?

Orders
OrderID CustomerID
1 1
2 2
3 3
4 1
5 2
6 3
7 456
8 443
9 3243
10 32443
11 234324

OrderDetails
1 1
2 1
2 2
2 3
3 1
3 2
3 3
3 4
3 5
3 6
3 7
4 1
4 2
4 3
4 4

THIS IS THE SIMPLE ONE
SELECT Orders.*, OrderDetails.LineItem
FROM Orders INNER JOIN OrderDetails ON Orders.OrderID =
OrderDetails.OrderID
WHERE OrderDetails.LineItem IN (Select Top 3 LineItem FROM OrderDetails
SUBQ WHERE SUBQ.OrderID = OrderDetails.OrderID)
ORDER BY 1, 3,2

THIS IS A RIGHT JOIN THAT WILL SHOW ALL ORDERS; EVEN WITHOUT LINEITEMS
SELECT Orders.OrderID, Orders.CustomerID, OrderDetails.LineItem
FROM Orders LEFT OUTER JOIN
OrderDetails ON Orders.OrderID =
OrderDetails.OrderID
WHERE (OrderDetails.LineItem IN
(SELECT TOP 3 LineItem
FROM OrderDetails AS SUBQ
WHERE (OrderID =
OrderDetails.OrderID))) OR OrderDetails.LineItem IS NULL
ORDER BY Orders.OrderID, OrderDetails.LineItem, Orders.CustomerID

RESULTS
OrderID CustomerID LineItem
1 1 1
2 2 1
2 2 2
2 2 3
3 3 1
3 3 2
3 3 3
4 1 1
4 1 2
4 1 3
5 2 NULL
6 3 NULL
7 456 NULL
8 443 NULL
9 3243 NULL
10 32443 NULL
11 234324 NULL


HTH Dog; let me know if i can help more

-Aaron
 
Izzy,

Not Quite.

I'm doing this in SS and get this error.

Msg 245, Level 16, State 1, Line 2
Conversion failed when converting the nvarchar value '34101-9 -SS' to data type smallint.

This is an item number (length 22) and its trying to convert to smallint???? I've checked the schema and it appears to be OK.

Here's my code.

use IMaster
select Inven.ActDate, Inven.Item, Inven.Descr, Inven.ProdLn,
Trans.TrnDate, Trans.TrnEffDate, Trans.Dept
from Inven inner join Trans on (Inven.ActDate = Trans.TrnDate and
Inven.Item = Trans.Item and Inven.ProdLn = Trans.ProdLn)
where Trans.TrnEffDate in (select top 3 Trans.TrnEffDate from Trans as subq
where subq.ActDate = Trans.TrnDate and subq.Item = Trans.Item and
subq.ProdLn = Trans.ProdLn)

Any Ideas?

Thanks for your Help,

Hexman
 
Hexman

Without knowing your schema it's almost impossible to say what the
issue is but from the sound of the error message it looks like one of
the joins is on two different field types (Inven.Item = Trans.Item as a
guess as you say that '34101-9-SS' is an item number). To diagnose,
check what field that value is held in in your DB, check your SQL
statement and see whether this field is used as part of the join - if
so, what's the field-type it's trying to join to.

HTH
Martin
 
you can take the subquery; drop the correlated part-- where you're
binding the subquery to the parent query.. and test it.

then test the parent query.

shit you can do this all in design view in either microsoft Access Data
Projects or SQL Server Management Studio

-Aaron
 
Heck, I found the error (my typo, the eyes, the eyes!!!). Works well under SS 2005 EE. Extremely long running under Access.

I thank all who have contributed.

Hexman
 
Access MDB?

Access MDB is completely obsolete
use Access Data Projects; avoid the headaches!

-Aaron
 
Back
Top