Temp Tables in MS Access - ms-access

Can we build Temp Tables for Queries in MS Access 2013? Or does everything have to be done in nested queries.
For Example:
Select
FacilityID
,ActivityID
ClientID
Into
#Clients
From
Activities
Then
do something like
Select
FacilityID
,Count(ClientID) Over (partition By ActivityID) as ActivityCount
Into
#Final
From
#Clients
This has been simplified- but you should have an idea.
Thanks,

Yes this is possible in Access if you run your queries from VBA code. You cannot use an action query like an Update or Make Table as a row source of another query so you have to build the source table first.
Dim db as DAO.Database
Set db = CurrentDb()
db.Execute _
"SELECT FacilityID, ActivityID, ClientID " & _
"INTO Clients " & _
"FROM Activities;", _
dbFailOnError
db.execute _
"SELECT FacilityID, ... " & _
"INTO Final " & _
"FROM Clients;", _
dbFailOnError
(The COUNT ... OVER (PARTITION BY ...) code was removed to prevent the false impression that Access SQL supports that construct. It doesn't.)

Related

Selecting fields command gives error

I want to sort multiple fields in an access data base but being a newbie I took reference from MSDN program and first trying to sort on a single field. I'm getting error From syntax wrong on the following lines.
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM Banks_Trnx_2018-2019" _
& "ORDER BY SNO DESC;")
The full program as follows.
Option Compare Database
Sub OrderByX()
Dim dbs As Database, rst As Recordset
' Modify this line to include the path to Northwind
' on your computer.
Set dbs = OpenDatabase("E:\FY_2018-2019\Banks\Banks_Trnx_2018-2019.accdb")
' Select the last name and first name values from
' the Employees table, and sort them in descending
' order.
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM Banks_Trnx_2018-2019" _
& "ORDER BY SNO DESC;")
' Populate the Recordset.
rst.MoveLast
' Call EnumFields to print recordset contents.
' EnumFields rst, 12
dbs.Close
End Sub
I am clueless. Please help. As already mentioned I would like to sort on three fields (multiple fields) comprising of text and numerical fields which presently I can easily do by setting columns in proper order and selecting them together while sorting. Since it is a repetitive operation I am trying to develop VBA procedure for the same. Any pointer in the right direction shall be highly appreciated.
You should set your sql to a variable first - makes it a lot easier to troubleshoot - you'd be able to see you've left out some spaces between keywords and table
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019]" _
& "ORDER BY SNO DESC;")
Should be (with added brackets for table as suggested by #skkakkar)
Set rst = dbs.OpenRecordset("SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019] " _
& "ORDER BY SNO DESC;")
You have a - in your table name. I didn't even think that was allowed, either put brackets around your table name or change the table name.
"SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018-2019]" _
& "ORDER BY SNO DESC;"
or
"SELECT ACT_CD, " _
& "SNO FROM [Banks_Trnx_2018_2019] " _
& "ORDER BY SNO DESC;"
and change table name.

Requerying subform only work sometimes

I am trying to requery a subform which diplays customer details.
I am sure my sql works as the subform works fine when not influenced by the main form.
Private Sub btnSearch_Click()
Dim sql As String
sql = "SELECT tblCustomer.[Job ID], tblCustomer.[Customer Name], tblCustomer.[Street Name], tblCustomer.Area, tblAppointments.[Appointment Date] " _
& "FROM tblCustomer " _
& "LEFT JOIN tblAppointments ON tblCustomer.[Job ID] = tblAppointments.[Job Number].Value " _
& "WHERE [Customer Name] LIKE '*" & Me.txtKeywords & "*'" _
& "OR [Job ID] LIKE '*" & Me.txtKeywords & "*'" _
& "OR [Street Name] LIKE '*" & Me.txtKeywords & "*'" _
& "OR [Area] LIKE '*" & Me.txtKeywords & "*'" _
& "OR [Appointment Date] LIKE '*" & Me.txtKeywords & "*'" _
& "ORDER BY tblAppointments.[Appointment Date];"
Me.subCustomerList.Form.RecordSource = sql
Me.subCustomerList.Form.Requery
End Sub
The debugger shows an error at the following line:
Me.subCustomerList.Form.RecordSource = sql
I also get the error message
object or class does not support set of events
Consider parameterization with a stored query for several reasons in your case:
Helps avoid syntax issues like what you may have since Access will not allow you to save a query with syntax errors if using the GUI query designer;
Better maintainability than a concatenated SQL string which requires single/double quote enclosure and you abstract data from code;
The Access engine compiles stored queries to best execution plan so will be more efficient than a VBA called SQL string (i.e., use index on JOIN).
SQL (save as a query object with parameter to be referenced by name in VBA)
PARAMETERS txtKeywordsParam TEXT(255);
SELECT c.[Job ID], c.[Customer Name], c.[Street Name], c.Area, a.[Appointment Date]
FROM tblCustomer c
LEFT JOIN tblAppointments a ON c.[Job ID] = a.[Job Number]
WHERE c.[Customer Name] LIKE txtKeywordsParam
OR c.[Job ID] LIKE txtKeywordsParam
OR c.[Street Name] LIKE txtKeywordsParam
OR c.[Area] LIKE txtKeywordsParam
OR a.[Appointment Date] LIKE txtKeywordsParam
ORDER BY a.[Appointment Date];
VBA
Private Sub btnSearch_Click()
Dim qdef As QueryDef
Dim rst As Recordset
' OPEN QUERY AND BIND PARAM
Set qdef = CurrentDb.QueryDefs("mySavedParamQuery")
qdef!txtKeywordsParam = "*" & Me.txtKeyword & "*"
' ASSIGN QUERY RESULT TO RECORDSET
Set rst = qdef.OpenRecordset()
' APPLY RECORDSET TO FORM
Set Me.subCustomerList.Form.Recordset = rst
Set qdef = Nothing
End Sub
I created a new subform and copied the one that did not work and everything seems to be running well.

Merge 2 fields and insert into table

hi i am trying to insert value into my output table 
in my Input table have 
profit  extra 
10         20 
when i insert into my output table it should get concatenated as 
cost 
1020 
sub test()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Set db = CurrentDb
db. execut "Insert into OUTPUT_TBL (DESCRIPTION,COST,DEBIT,CREDIT) " & _
" SELECT INPUT.DESCRIPTION,((INPUT.PROFIT)+(INPUT.EXTRA)) AS COST," & _
" IIF(EXTERNAL.SOLUTION='DEBIT',(AMOUNT),0) as DEBIT, " & _
" IIF(EXTERNAL.SOLUTION='CREDIT',(AMOUNT),0) AS CREDIT " & _
" FROM INPUT , EXTERNAL"
db.close
end test
when i try to run it i am getting error as  run time error 3075
Couple issues - noticed a typo, it should be db.execute "" not db.execut
Also, for string concatenation use & in Access SQL. 3075 means you used a bad operator.
Another thing, You may also need to add a JOIN to the SQL.
For example, to get you on the right track:
db.execute "Insert into OUTPUT_TBL (DESCRIPTION,COST,DEBIT,CREDIT) SELECT INPUT.DESCRIPTION,((INPUT.PROFIT)&""&(INPUT.EXTRA)) AS COST,IIF(EXTERNAL.SOLUTION='DEBIT',(AMOUNT),0) as DEBIT, IIF(EXTERNAL.SOLUTION='CREDIT',(AMOUNT),0) AS CREDIT from INPUT JOIN EXTERNAL ON INPUT.KEY=EXTERNAL.KEY"

Using SQL in Query that auto updates

Thank you beforehand for your assistance. I know enough about Access, SQL, and VBA to get myself into trouble. Here is what I want to do.
I want to create a query that starts with a certain year and then lists each year up until the current year. The problem is that I want the query to automatically update as time progresses. In other words, say the start year is 2009, I want my query to list 2009, 2010, 2011, 2012, and 2013 since we are currently in the year 2013. Next year, the list will expand to include 2014. I suspect this is possible using a query in SQL but not sure how to go about coding it properly.
I bet that there is no simple solution for this simple process. We must use VBA to perform following steps:
Create a temporary table:
CREATE Table tblTmpYears (
ID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY,
Year Long
);
In VBA:
Dim strSQL
strSQL = "CREATE Table tblTmpYears (" _
& " ID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY," _
& " Year Long" _
& ");"
CurrentDb.Execute strSQL, dbFailOnError
Fill the temporary table:
INSERT INTO tblTmpYears (year) VALUES (2009);
INSERT INTO tblTmpYears (year) VALUES (2010);
INSERT INTO tblTmpYears (year) VALUES (2011);
INSERT INTO tblTmpYears (year) VALUES (2012);
INSERT INTO tblTmpYears (year) VALUES (2013);
In VBA, for 5 years, valid even after 100 years after our life existence:
Dim y as long, ymin, ymax, strSQL
ymax = Year(Date)
ymin = ymax - 4
For y = ymin to ymax
strSQL = "INSERT INTO tblTmpYears (Year) VALUES (" & y & ");"
CurrentDb.Execute strSQL, dbFailOnError
Next
Create a query for listing with the temporary table:
SELECT * FROM tblStudents INNER JOIN tblTmpYears
ON tblStudents.Year=tblTmpYears.Year
ORDER BY Year;
In VBA like this:
Dim qdf, strSQL
strSQL = "SELECT * FROM tblStudents INNER JOIN tblTmpYears" _
& " ON tblStudents.Year=tblTmpYears.Year" _
& " ORDER BY Year;"
Set qdf = CurrentDB.CreateQueryDef("qrySelTemporary", strSQL)
DoCmd.OpenQuery qdf.Name
Here you will have the Query Datasheet Windows with your students's list, it's printable. Even better, you can use it as
MyReport.RecordSource = "qrySelTemporary"
in an Access Report with a beautiful presentation.
Delete the temporary table after printing, for example:
DROP TABLE tblTmpYears;
In VBA:
Dim strSQL
strSQL = "DROP TABLE tblTmpYears;"
CurrentDb.Execute strSQL, dbFailOnError
Only VBA can accomplish this... rather than a single SQL query.
How about this - a small VBA function that outputs the SQL for an appropriate UNION query, which you can then assign as the RowSource for a combo box, use as a sub-query inside another dynamically generated query, or whatever:
Function CreateYearsToCurrentSQL(From As Integer) As String
Dim I As Integer, S As String
For I = From To Year(Date)
If I <> From Then S = S + "UNION "
S = S + "SELECT " & I & " AS Year FROM MSysObjects" + vbNewLine
Next I
CreateYearsToCurrentSQL = S
End Function
The FROM MSysObjects is because Access will whinge about no FROM clause if one isn't there, and MSysObjects is bound to be an existing table in an Access context (if you prefer though, replace it with the name of any other table).
So I managed to create a Query Criteria that does what I need.
Like (Right(Year(Now()),2)-3) & "-" Or Like (Right(Year(Now()),2)-2) & "-" Or Like (Right(Year(Now()),2)-1) & "-" Or Like Right(Year(Now()),2) & "-"
Thank you everyone for your efforts.

VBA Access - Multiple Tables count by date

We'd like to count from an Access database that has multiple tables - about 50.
We need to count from 1 column in each table that is 'QCPASS' This is a check box - if a product passed the box was checked if failed then not. We need to count both for EACH table, also allowing the user to specify a date range from a date column that exists in every table.
I've tried this with a query but I am told the query is unable to select, count and do the date range. Any VBA help would be great.
Exporting to Excel would be great, but any results would be fine. Here is the query I created that counts in a column from each table passes and failures. I can't iterate with a query either, so VBA seems the way to go:
SELECT "Table1" , Count('qcpass') AS column
FROM 5000028
GROUP BY [5000028].qcpass
union
SELECT "Table2",count('qcpass')
FROM 5000029
Group By [5000029].qcpass;
You can traverse the full TableDefs collection in your database, and create a query using VBA.
A word of warning: The TableDefs collection has the Access database system tables, so you need to skip this. A way I suggest you is to check for a specific table name prefix (it is noted in the code below).
public sub createMyBigUnionQuery()
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourFinalQuery", strSQL
db.close
exit sub
Notice that you can define any valid query you want. Take this as a hint, and tweak it to fit your specific needs.
Hope this helps you
Adressing #HansUp comment, if you need to filter your data by date, you have two options:
Include the where condition on every select created by the procedure
Include the date field in your query and group by it, and create a second query to filter the data you need from the created query.
I would personally go with option 1, and here is a sample code:
public sub createMyBigUnionQueryWithDates(d0 as date, d1 as date)
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourOtherFinalQuery", strSQL
db.close
exit sub
The reason I use cDbl(d0) is because Access dates are sensitive to regional settings, and I've had a lot of headaches dealing with it. Access (and many other Microsoft products) store dates as floating-point numbers (the integer part is the date, and the decimal part is the time).
Another word of warning: If your dates don't include time, then the between condition will work. But if they do include time, then I recommend you change the where condition to this:
"where rowDate >= " & cDbl(d0) & " and rowDate < " & cDbl(d1 + 1)"