Selecting fieldnames dynamically based on date in Query [closed] - sql

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I have a table with multiple fields in MS access. These fields have field names representing periods of time, such as 2011_2, 2011_3,..., 2013_9, 2013_10, ... , 2015_1, 2015_2...
How do I run a query that selects the next 12 months as the needed fields based on today's date? i.e, if today is 22 Dec 2013, it selects the fields : 2013_12, 2014_1, 2014_2, ..., 2014_12?
Thanks a bunch.

The short answer to your question is that you can't have dynamic field names in the Access query builder. Ideally, you should modify your data so that you have one date field. That way you can specify a date range for that field in the query criteria that doesn't require the gymnastics below.
If that's not possible, though, the long answer is that you'll need to use VBA code to construct your query. The code below should create a new query in your database (cleverly called "YourQuery") that will contain the fields you need.
Since I don't know what your table is called, it'll be "table" in this example. You should change it to whatever your table is if you use this code.
You'll need to install this code in a VBA module in your database, and then devise some means of calling the function to produce the new query. For example, you could create a macro using the "RunCode" action that uses "DynamicQuery()" as the procedure to run. Note that the function call will fail if the query for this month already exists so delete that manually if you need to run it again for some reason (you could also add additional code to function to accomplish this).
Again, just because you can do something doesn't mean you should. You really should redesign your table so you don't have to resort to workarounds like this.
Public Function DynamicQuery()
Dim strSQL As String
dim datFieldDate As Date
Dim strYearMonth As String
Dim strThisMonth As String
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim i As Integer
Set dbs = CurrentDb
strThisMonth = Year(Date) & "_" & Month(Date)
strSQL = "SELECT table." & strThisMonth
For i = 1 to 12
datFieldDate = DateAdd("m",i,Date)
strYearMonth = Year(datFieldDate) & "_" & Month(DatFieldDate)
strSQL = strSQL & ", table." & strYearMonth
Next i
strSQL = strSQL & " FROM table;"
Set qdf = dbs.CreateQueryDef("YourQuery_" & strThisMonth, strSQL)
Set qdf = Nothing
Set dbs = Nothing
End Function

If you have a form in Access with a button on it you could create the SQL statement in code as a string, eg:
MyString = "SELECT " & Year(Now) & "_9" & " FROM myTable....."
You can then execute it via code.
You won't be able to create a "standard" query that dynamically builds a list of fields to select.

Related

Setting two rowsources in same procedure is terrible slow - Access 2010

I have two Listboxes which are filled via vba on a click event. The table 'Project' is a odbc datasource with 250 records.
List1.RowSource = "SELECT Name FROM Project WHERE ProjectID = " & ProjectID.Caption & " AND Year = " & ActualYear.Caption & " ORDER BY Name"
List2.RowSource = "SELECT ProjectShare FROM Project WHERE ProjectID = " & ProjectID.Caption & " AND Year = " & ActualYear.Caption & " ORDER BY Name"
So far so good. But when I run this code, it takes everytime up to 30sec to complete. I thought, okay it's because of odbc and so on. But when I run only one line of this code (no matter which), it is fast as lightning (0,1sec).
How can it be, that one query takes 0,1sec and two querys 30sec? May I could make a break between these two lines? Btw. without odbc everything works like a charm, no matter how many lines
You can bind both listboxes to the same recordset by manually creating the recordset. This allows Access to only query the table once instead of twice at the same time, avoiding any locking conflicts, and tends to avoid other problems as well.
This also allows you to use parameters, fixing any errors introduced by string concatenation.
Dim rs As DAO.Recordset
With CurrentDb.CreateQueryDef("", "SELECT Name, ProjectShare FROM Project WHERE ProjectID = p1 AND Year = p2 ORDER BY Name")
.Parameters(0).Value= ProjectID.Caption
.Parameters(1).Value = ActualYear.Caption
Set rs = .OpenRecordset(dbOpenSnapshot) 'Snapshot because it won't be updated
End With
Set list1.Recordset = rs
Set list2.Recordset = rs
Note that I have had errors occur when an object bound to a recordset with parameters was requeried, so you might want to use string concatenation if that's happening.

SQL Query in Access not applying WHERE clause

I am an amateur vba programmer currently struggling with the following:
I wrote a simple SQL Query for my VBA program to extract data from an existing Query (GroupedData) in Access:
Dim strSQL as string
Dim db as dao.database
dim rs as dao.recordset
strSQL = "SELECT GroupedData.EmployeeID, GroupedData.End, GroupedData.LOB, GroupedData.Position, GroupedData.WorkStatus " & _
"FROM GroupedData WHERE (((GroupedData.End) Is Null) AND ((GroupedData.Position)=0) AND ((GroupedData.WorkStatus)=0));"
Set db = OpenDatabase(MY_DB, dbOpenDynaset)
Set rs = db.openrecordset(strSQL, dbOpenSnapshot)
Do While Not rs.EOF
ListBox1.AddItem rs!EmployeeID
rs.MoveNext
Loop
So my problem is that SQL is running smoothly but is not applying any filters (that is where clause - it produces records where workstatus and position contain values above 0)
I have done such queries in the past without having any issues. This time however I am stuck
Any help would be much appreciated!
Thank you
Ok i have fixed the issue. Here is what happened:
I have made a separate function that was retrieving Employee Name based on EmployeeID. But in that function i had recordset and database declared the same way, that is: rs and db. What happened when i ran the query was it was taking the first record filtered but then the rest of them were unfiltered because they were based on the recordset within the function (which is of course all of the employees) Such a silly mistake :) Thanks anyways

Microsoft Access 2010 - Dynamic query

I have an access web database that several users will need to log in to. The database contains a table of products.
The challenge is, every user needs to only see a subset of these products and never see the whole list.
At the moment i have some code to modify an existing query based on the logged in user's details. As they log in, some tempvars are created and these are used to modify the query criteria.
This works well when the first user logs in, but the moment the next user logs in, the query is modified again and the product list refreshes and now his products are shown and not the first users! Im thinking i need to dynamically create a permanent query for each user on log in?
Or is a better way to accomplish what im trying ? im quite new to access and struggling. Can anyone assist please?
Here is my code so far:
Button on login form has the following code that collects the user's details
Private Sub cmdLoginMine_Click()
Dim ID as long, strEmpName as string,strZondsc as string,strgrpdsc as string
ID = DLookup("ID", "Employees", "Login='" & Me.txtUser.Value & "'")
strEmpName = DLookup("FullName", "Employees", "Login='" & Me.txtUser.Value & "'")
strgrpdsc = DLookup("MyGrpdscs", "Employees", "Login='" & Me.txtUser.Value & "'")
strzondsc = DLookup("MyZondscs", "Employees", "Login='" & Me.txtUser.Value & "'")
TempVars.Add "tmpEmployeeID", ID
TempVars.Add "tmpEmployeeName", txtUser.Value
I then call a function that modifies the existing query, populating it with this users details for the criteria
qryEdit strgrpdsc, strzondsc, ID
Sub qryEdit(strgrpdsc As String, strzondsc As String, ID As Long)
Dim qdf As DAO.QueryDef
Dim qdfOLD As String
Set qdf = CurrentDb.QueryDefs("InventoryQryforDS")
With qdf
.SQL = "SELECT Products.ProductCode, Products.ProductName, Products.GRPDSC, Categories.Category, Inventory.Available " & _
"FROM (Categories INNER JOIN Products ON Categories.ID = Products.CategoryID) INNER JOIN Inventory ON Products.ID = Inventory.ProductID " & _
"WHERE Products.GRPDSC in (" & strgrpdsc & ") and Categories.Category in (" & strzondsc & ") and products.ownersid =" & ID & _
" ORDER BY Products.ProductCode"
End With
Set qdf = Nothing
End Sub
The results of the query are shown on a form, which is what is currently requerying and showing the wrong data.
Thanks
EDIT - THe data is shown on a form, linked to one of the new style navigation buttons as shown.The recordsource property of the form is the query that's populated as described above.
I have a few suggestions/corrections to your approach to solving this issue.
When using DLookup, make sure they are enclosed within Nz() function, if the value you are looking for is not found you might be facing troubles of assigning a Null value to a Data Type that cannot handle Null. Anything other than Variant type will suffer.
You seem to do not one but four DLookup's on the table. This could be very expensive. This could be minimized by using a simple RecordSet Object.
I would not use TempVars much as they could be tricky to understand and implement.
Why are you editing the Query? This could again be a bit expensive in terms of memory. How are you showing the list of Products? In DataSheet or ComboBox or LsitBox? You could yet again change the RecordSource or RowSource of the Objects rather than editing the Query itself.
Finally, your users should all have a separate copy of the Front End file. Not one copy used by 20-30 people. If the files is restricted to be used by one person, then the code should work regardless of being modified. As the user will have access to the right data at all times.

How to run a SQL select statement in VB

I have been looking around but can't seem to find out how to do this.
I'm trying to execute a SELECT sql statement in VB that takes in a parameter from a form. For example the user selects a From and a To date and the SQL should take what they selected.
I know that you cannot use the DoCmd.Execute method for SELECT SQL so I would need to open the record set - but how? This is what I have tried so far
Dim recordSet As DAO.recordSet
Dim SQL As String
SQL = "SELECT * FROM tblWebMeetingData"
Set recordSet = CurrentDb.OpenRecordset(SQL)
'More code in here
recordSet.Close
Set recordSet = Nothing
Because this executes without an error I assume it's actually getting the results - so is there a way to see what it is actually returning?
Thanks
First: It's a good advice to rename the recordset to rs, for example, because "recordset" is a reserved name. This is misunderstandable.
This recordset contains the records you queried by your SQL statement. You may access those data by rs.fields("fieldname").value. Move to the next recordset with rs.movenext.
To incorporate the form's control value I use the way to build the full SQL statement prior to opening the recordset. Say the form is named "myform" and the control "mycontrol", you may write some kind of
SQL = "SELECT * FROM tblWebMeetingData WHERE myfield = " & forms!myform.mycontrol.value
Please be sure the form only contains valid values, because any wrong formatted value will directly lead to an SQL execution error.
I hope it was this, what you wanted.
Here you have come sample code about iterating trought RecordSet and using values from it( I hope it helps a bit):
Dim i As Integer
Do While Not rs.EOF
Sheets("D_" & day).Cells(i, 1) = rs.Fields(0).Value
Sheets("D_" & day).Cells(i, 2) = rs.Fields(1).Value
rs.MoveNext
i = i + 1
Loop
rs.Close

Access 2007 VBA Query Shows Data in Query Analyzer But Not in VBA Coded Recordset

I have a function I've written that was initially supposed to take a string field and populate an excel spreadsheet with the values. Those values continually came up null. I started tracking it back to the recordset and found that despite the query being valid and running properly through the Access query analyzer the recordset was empty or had missing fields.
To test the problem, I created a sub in which I created a query, opened a recordset, and then paged through the values (outputting them to a messagebox). The most perplexing part of the problem seems to revolve around the "WHERE" clause of the query. If I don't put a "WHERE" clause on the query, the recordset always has data and the values for "DESCRIPTION" are normal.
If I put anything in for the WHERE clause the recordset comes back either totally empty (rs.EOF = true) or the Description field is totally blank where the other fields have values. I want to stress again that if I debug.print the query, I can copy/paste it into the query analyzer and get a valid and returned values that I expect.
I'd sure appreciate some help with this. Thank you!
Private Sub NewTest()
' Dimension Variables
'----------------------------------------------------------
Dim rsNewTest As ADODB.Recordset
Dim sqlNewTest As String
Dim Counter As Integer
' Set variables
'----------------------------------------------------------
Set rsNewTest = New ADODB.Recordset
sqlNewTest = "SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, " & _
"dbo_part.partdescription as Description, dbo_partmtl.qtyper as [Qty Per] " & _
"FROM dbo_partmtl " & _
"LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum " & _
"WHERE dbo_partmtl.mtlpartnum=" & Chr(34) & "3C16470" & Chr(34)
' Open recordset
rsNewTest.Open sqlNewTest, CurrentProject.Connection, adOpenDynamic, adLockOptimistic
Do Until rsNewTest.EOF
For Counter = 0 To rsNewTest.Fields.Count - 1
MsgBox rsNewTest.Fields(Counter).Name
Next
MsgBox rsNewTest.Fields("Description")
rsNewTest.MoveNext
Loop
' close the recordset
rsNewTest.Close
Set rsNewTest = Nothing
End Sub
EDIT: Someone requested that I post the DEBUG.PRINT of the query. Here it is:
SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, dbo_part.partdescription as [Description], dbo_partmtl.qtyper as [Qty Per] FROM dbo_partmtl LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum WHERE dbo_partmtl.mtlpartnum='3C16470'
I have tried double and single quotes using ASCII characters and implicitly.
For example:
"WHERE dbo_partmtl.mtlpartnum='3C16470'"
I even tried your suggestion with chr(39):
"WHERE dbo_partmtl.mtlpartnum=" & Chr(39) & "3C16470" & Chr(39)
Both return a null value for description. However, if I debug.print the query and paste it into the Access query analyzer, it displays just fine. Again (as a side note), if I do a LIKE statement in the WHERE clause, it will give me a completely empty recordset. Something is really wonky here.
Here is an interesting tidbit. The tables are linked to a SQL Server. If I copy the tables (data and structure) locally, the ADO code above worked flawlessly. If I use DAO it works fine. I've tried this code on Windows XP, Access 2003, and various versions of ADO (2.5, 2.6, 2.8). ADO will not work if the tables are linked.
There is some flaw in ADO that causes the issue.
Absolutely I do. Remember, the DEBUG.PRINT query you see runs perfectly in the query analyzer. It returns the following:
Job/Sub Rev Description Qty Per
36511C01 A MAIN ELECTRICAL ENCLOSURE 1
36515C0V A VISION SYSTEM 1
36529C01 A MAIN ELECTRICAL ENCLOSURE 1
However, the same query returns empty values for Description (everything else is the same) when run through the recordset (messagebox errors because of "Null" value).
I tried renaming the "description" field to "testdep", but it's still empty. The only way to make it display data is to remove the WHERE section of the query. I'm starting to believe this is a problem with ADO. Maybe I'll rewriting it with DAO and seeing what results i get.
EDIT: I also tried compacting and repairing a couple of times. No dice.
When using ADO LIKE searches must use % instead of *. I know * works in Access but for some stupid reason ADO won't work unless you use % instead.
I had the same problem and ran accoss this forum while trying to fix it. Replacing *'s with %'s worked for me.
Description is a reserved word - put some [] brackets around it in the SELECT statement
EDIT
Try naming the column something besides Description
Also are you sure you are using the same values in the where clause - because it is a left join so the Description field will be blank if there is no corresponding record in dbo_part
EDIT AGAIN
If you are getting funny results - try a Compact/Repair Database - It might be corrupted
Well, what I feared is the case. It works FINE with DAO but not ADO.
Here is the working code:
Private Sub AltTest()
' Dimension Variables
'----------------------------------------------------------
Dim rsNewTest As DAO.Recordset
Dim dbl As DAO.Database
Dim sqlNewTest As String
Dim Counter As Integer
' Set variables
'----------------------------------------------------------
sqlNewTest = "SELECT dbo_partmtl.partnum as [Job/Sub], dbo_partmtl.revisionnum as Rev, " & _
"dbo_part.partdescription as [TestDep], dbo_partmtl.qtyper as [Qty Per] " & _
"FROM dbo_partmtl " & _
"LEFT JOIN dbo_part ON dbo_partmtl.partnum = dbo_part.partnum " & _
"WHERE dbo_partmtl.mtlpartnum=" & Chr(39) & "3C16470" & Chr(39)
Debug.Print "sqlNewTest: " & sqlNewTest
Set dbl = CurrentDb()
Set rsNewTest = dbl.OpenRecordset(sqlNewTest, dbOpenDynaset)
' rsnewtest.OpenRecordset
Do Until rsNewTest.EOF
For Counter = 0 To rsNewTest.Fields.Count - 1
MsgBox rsNewTest.Fields(Counter).Name
Next
MsgBox rsNewTest.Fields("TestDep")
rsNewTest.MoveNext
Loop
' close the recordset
dbl.Close
Set rsNewTest = Nothing
End Sub
I don't use DAO anywhere in this database and would prefer not to start. Where do we go from here?
I know some time has passed since this thread started, but just in case you're wondering, I have found out some curious about Access 2003 and the bug may have carried over to 2007 (as I can see it has).
I've had a similar problem with a WHERE clause because I needed records from a date field that also contained time, so the entire field contents would look like #6/14/2011 11:50:25 AM# (#'s added for formatting purposes).
Same issue as above, query works fine with the "WHERE ((tblTransactions.TransactionDate) Like '" & QueryDate & "*');" in the query design view, but it won't work in the VBA code using ADO.
So I resorted to using "WHERE ((tblTransactions.TransactionDate) Like '" & QueryDate & " %%:%%:%% %M');" in the VBA code, with ADO and it works just fine. Displays the record I was looking for, the trick is not to use "*" in the Like clause; or at least that was the issue in my case.
I put brackets around the word "Description" in the SELECT statement, but it's behavior remains. It works fine as long as I don't put anything in the WHERE clause. I've found if I put anything in the where clause, the description is blank (despite showing up in the Query analyzer). If I use a LIKE statement in the WHERE clause, the entire recordset is empty but it still works properly in the Query Analyzer.
Ultimately I think it's a problem with running ADO 2.8 on Vista 64
Personally I have always used DAO in Access projects.