Hi all! I wonder if anyone could offer advice - I am not exactly an SQL gun and have been playing with this for a day now. Any nudges in the right direction would be very much appreciated.
I am trying to create a query based on 2 linked tables, that gives me a grouped list of IDs from table 1 and a the latest date in table 2 for a row that has the same ID as table 1
So for example I have 2 tables.
table1 includes
MyID - primary key
MyName
table2 includes
ID
MyID - foreign key
MyDate
MyComment
I want to find table2.MyComment for the latest table2.MyDate where table2.MyID matches table1.MyID (eg the grouping level).
So say table1 is - MyID Myname
-
1 name1
-
2 name2
and table2 is - ID MyID MyDate MyComment
-
1 1 1/1/12 Comment1
-
2 1 2/1/12 Comment2
-
3 2 1/1/12 Comment3
My query should return - MyID MyName MyComment
-
1 name1 Comment2
-
2 name2 Comment3
I have been able to achieve this using the following: - =Dlookup("[MyComment]","table2","[MyID] = " & [MyID] & " And datevalue([MyDate]) = #" & format(dmax("[MyDate]","table2","[MyID] = " & [MyID]),"mm/dd/yyyy") & "#")
in a continuous form with table1 as the recordsource but it is very slow, so I'm hoping to replace this with a single query I can use as the recordsource.
Where I am stuck is what syntax to use for the query. In single instances of dcount in a continuous form I can just refer to a field in the current row, if that makes sense but not sure how to do it in SQL.
I have got as far as this - SELECT table1.myID
-
, table1.MyName
-
, table2.MyComment WHERE MyDate = MAX(SELECT MyDate FROM table2 WHERE table2.MyID = table1.MyID)
-
FROM table1 INNER JOIN table2 ON table1.MyID = table2.MyID
-
GROUP BY table1.MyID;
But this gives me a syntax error (missing operator) in the WHERE statement, I suspect I am referencing the tables and fields wrong and I also wonder if there is a completely different way to go about this?
I have also tried using the query builder but with no success yet. I have had a search on this forum but I could only find examples querying a single table.
The way I think of these queries is to break them up into small chunks:
Starting with table2:
What you want is the last (max) date of each entry made by the my id. So you need to group on the user ID and return the max date. Call this Q1
(myid,mydate) = (1,2/1/12) and (2,1/1/12)
SQL - SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID;
This is great now we need the comment associated with these... well only two records will match so do a simple inner join with table2 against the agregate query Q1 on the FK_Myid and the MyDate fields. Show the fields from table 2 that we're interested in. Call this Q2
(PK_tbl2, FK_MyID, MYDate, Comment)=
(2, 1, 2/12/2012, Comment2)
(3, 2, 1/1/2012, Comment3)
SQL - SELECT
-
Table2.PK_Tbl2,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table2
-
INNER JOIN Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID);
Finally we need to get the names from table one... easy same inner join on table1 and q2 showing the name field from table1 and the date and comment from q2. Call this Q3
(Q2!PK_tbl2, Table1!MyName, Q2!MYDate, Q2!Comment)=
(2, Name1, 2/12/2012, Comment2)
(3, Name2, 1/1/2012, Comment3)
SQL -Q3: - SELECT
-
Q2.PK_Tbl2,
-
Table1.MyName,
-
Q2.MyDate,
-
Q2.Comment
-
FROM Table1
-
INNER JOIN Q2
-
ON Table1.MyID = Q2.FK_MyID;
So the final SQL looks like: - SELECT
-
Q2.PK_Tbl2,
-
Table1.MyName,
-
Q2.MyDate,
-
Q2.Comment
-
FROM Table1
-
INNER JOIN
-
( SELECT
-
Table2.PK_Tbl2,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table2
-
INNER JOIN
-
(SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID)
-
AS Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID))
-
AS Q2
-
ON Table1.MyID = Q2.FK_MyID;
-edit- found typo
Ofcourse, in Q2 you could go ahead and add in table1 to get the name value so you'd get something like: - SELECT
-
Table2.PK_Tbl2,
-
Table1.MyName,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table1
-
INNER JOIN
-
(Table2
-
INNER JOIN
-
(SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID)
-
AS Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID))
-
ON Table1.MyID = Table2.FK_MyID;
Which I think looks a little neater and one less sub.
Now I'm sure there are more elegant ways of doing this, and I understand that the subqueries can slow things down on large databases; however, I've returned 100's of records from my databases with just such a query (well, same concept) in just a blink of an eye.
5 5061
Try moving your WHERE clause to between lines 4 & 5. This would leave you with: - SELECT...
-
FROM...
-
WHERE...
-
GROUP BY...
Cheers for the reply!
I tried your suggestion but got error 'Cannot have aggregate function in WHERE clause (MAX()=)'
A little googling suggested I need to use HAVING instead of where so I ended up with: - SELECT
-
tblProjects.Project_Number,
-
tblProjects.Project_Name,
-
tblProjectStatus.Exec_Status
-
FROM tblProjects
-
INNER JOIN tblProjectStatus
-
ON tblProjects.Project_Number
-
tblProjectStatus.Project_Number
-
GROUP BY tblProjects.Project_Number
-
HAVING Date_Updated =
-
MAX(SELECT
-
Date_Updated
-
FROM tblProjectStatus
-
GROUP BY tblProjects.Project_Number
-
HAVING tblProjectStatus.Project_Number =
-
tblProjects.Project_Number);
Which unfortunately produces 'cannot have aggregate function in expression (MAX()=)'
So it seems I might not be able to use MAX in this way - is there an alternative?
In your nested query, replace the HAVING with WHERE as the HAVING isn't needed. Unfortunately, I don't have a database that I can test this with, but that I what I'm reading from the error message. So your last line would be (broken down for easier reading): - HAVING Date_Updated = MAX(
-
SELECT Date_Updated
-
FROM tblProjectStatus
-
GROUP BY tblProjects.Project_Number
-
WHERE tblProjectStatus.Project_Number = tblProjects.Project_Number
-
);
zmbd 5,501
Expert Mod 4TB
The way I think of these queries is to break them up into small chunks:
Starting with table2:
What you want is the last (max) date of each entry made by the my id. So you need to group on the user ID and return the max date. Call this Q1
(myid,mydate) = (1,2/1/12) and (2,1/1/12)
SQL - SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID;
This is great now we need the comment associated with these... well only two records will match so do a simple inner join with table2 against the agregate query Q1 on the FK_Myid and the MyDate fields. Show the fields from table 2 that we're interested in. Call this Q2
(PK_tbl2, FK_MyID, MYDate, Comment)=
(2, 1, 2/12/2012, Comment2)
(3, 2, 1/1/2012, Comment3)
SQL - SELECT
-
Table2.PK_Tbl2,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table2
-
INNER JOIN Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID);
Finally we need to get the names from table one... easy same inner join on table1 and q2 showing the name field from table1 and the date and comment from q2. Call this Q3
(Q2!PK_tbl2, Table1!MyName, Q2!MYDate, Q2!Comment)=
(2, Name1, 2/12/2012, Comment2)
(3, Name2, 1/1/2012, Comment3)
SQL -Q3: - SELECT
-
Q2.PK_Tbl2,
-
Table1.MyName,
-
Q2.MyDate,
-
Q2.Comment
-
FROM Table1
-
INNER JOIN Q2
-
ON Table1.MyID = Q2.FK_MyID;
So the final SQL looks like: - SELECT
-
Q2.PK_Tbl2,
-
Table1.MyName,
-
Q2.MyDate,
-
Q2.Comment
-
FROM Table1
-
INNER JOIN
-
( SELECT
-
Table2.PK_Tbl2,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table2
-
INNER JOIN
-
(SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID)
-
AS Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID))
-
AS Q2
-
ON Table1.MyID = Q2.FK_MyID;
-edit- found typo
Ofcourse, in Q2 you could go ahead and add in table1 to get the name value so you'd get something like: - SELECT
-
Table2.PK_Tbl2,
-
Table1.MyName,
-
Table2.FK_MyID,
-
Table2.MyDate,
-
Table2.Comment
-
FROM Table1
-
INNER JOIN
-
(Table2
-
INNER JOIN
-
(SELECT
-
Table2.FK_MyID,
-
Max(Table2.MyDate)
-
AS MaxOfMyDate
-
FROM Table2
-
GROUP BY Table2.FK_MyID)
-
AS Q1
-
ON (Table2.MyDate = Q1.MaxOfMyDate)
-
AND (Table2.FK_MyID = Q1.FK_MyID))
-
ON Table1.MyID = Table2.FK_MyID;
Which I think looks a little neater and one less sub.
Now I'm sure there are more elegant ways of doing this, and I understand that the subqueries can slow things down on large databases; however, I've returned 100's of records from my databases with just such a query (well, same concept) in just a blink of an eye.
Thank you very much Seth & zmbd - I have followed your advice and learnt a bit in the process. I'm using zmbd's suggestion and following the logic have been able to make a few changes to get it doing exactly what I want.
Cheers!
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Freelobly Li |
last post by:
Hi all, I have encountered two problems when using linked tables; the linked
table is connected to SQL server 2000.
1) How can I add the N prefix of a string constant in a query in order to...
|
by: Mike D |
last post by:
now and again i've noticed that the Received field in a table linked
from an Exchange server will have an invalid date. the invalid date
always seems to be some day and some month in the year...
|
by: Michael Plant |
last post by:
Hello one and all.
I have a stored table in my database and the form I'm using is based on a
query that draws data from my stored table and a linked table. The linked
table is a *.txt file.
...
|
by: Shannan Casteel via AccessMonster.com |
last post by:
I would like to be able to use 4 text boxes (i.e. Part #, Description,
Quantity, Price) for up to 40 parts. However, only the Part # and Quantity
will be entered. The Description and Price will...
|
by: Bob Alston |
last post by:
Anyone know a way to make all access to a linked table, in another
Access MDB, read only?
I really don't want all the hassle of implementing full access security.
I can't do this at the server...
|
by: Wayne Wengert |
last post by:
I am trying to create a VB.NET Windows application to move some data from a
local Access DB table to a table in a SQL Server. The approach I am trying
is to open an OLEDB connection to the local...
|
by: RayPower |
last post by:
I'm having problem with using DAO recordset to append record into a
table and subsequent code to update other tables in a transaction. The
MDB is Access 2000 with the latest service pack of JET 4....
|
by: AustinClark |
last post by:
During login and logout, the workstations on my network dump some info into a text file. Part of this info is the current date and time, rendered by doing "echo %date%,%time%" at the command line.
...
|
by: nhkam |
last post by:
I am using MS Access 2007
I have a transaction table which holds all records with posting date on each of them. I used a make table query to find out the max date hold in the transaction table and...
|
by: grego9 |
last post by:
I have two tables that are linked by a common field called 'reference'. i am running a query and want the query to post a text of "EXCHANGE OV CHANGE" against each record where a field called "ORIG...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
| |