0

I am trying to write code that makes a collection of associate IDs (Associates is the name of my collection). There are 10 associates at any given time, but the collection will change based on who did what work this month. So once the collection has been made, I want to loop through it and make an SQL statement for each item. Some thing kind of like this:

        For Each Item In Associates
            qryTopSQL = "SELECT TOP " & QA# & _
            " Date, ID, [L#], Deal, RndNum FROM tbl_Data WHERE Date Between #" & _
            StartDate & "# And #" & EndDate & "# AND ID = " & Associates() & _
            " ORDER BY RndNum"
        Next Item

So I end up with however many SQL strings, but I'm having problems with this:

  1. Am I writing the ID = " & Associates() & " part correctly?
  2. How will it name these different strings so that I may access them later?
  3. Once it makes these, I'd like to do a UNION ALL query for all the SQL strings. How would I do this?

Please help if you can, it's greatly appreciated. I'm new to collections and arrays and I don't understand some of the things I've found online.

EDIT for an update: I tried this:

j = 1
k = 1
For Each Item In Associates
    If j = 1 And k = 1 Then
        qryTopString1 = "SELECT * FROM qryTopSQL_" & k
    Else
        qryTopString2 = " UNION ALL SELECT * FROM qryTopSQL_" & k
    End If
j = j + 1
k = k + 1
Next Item

'
Set qryTopUnionqdef = CurrentDb.CreateQueryDef("qryTopSQLUnion", qryTopString1 & qryTopString2)

But the resulting query is a union between the first and last TopSQLs, and none in the middle. Clearly the loop at this point it the problem but I can't figure out what to do thus far.

msim
  • 353
  • 7
  • 25
  • also if an array is better suited to my needs, please let me know – msim Feb 12 '15 at 23:50
  • Will *QA#*, *StartDate*, and *EndDate* be the same in all 10 of the `SELECT` statements? – HansUp Feb 13 '15 at 01:06
  • 1
    As HansUp alluded to, if all the other variables are remaining the same with the only thing changing being the Associate IDs, you can loop through your collection (or array of correct scalar type) and just form the proper input for the SQL IN operator, then pop it in your WHERE clause. The performance would be much better just a cleaner solution in general. Also, I think you should be referring to Item and not Associates() in your code as Item is the representation of the current item in the collection. – VBlades Feb 13 '15 at 01:41
  • @HansUp, yes, QA#, StartDate, and EndDate are the same for all 10. – msim Feb 13 '15 at 21:16

1 Answers1

0

In Access there are two ways to create query objects: VBA queries (in code) or stored queries (using ribbon, wizard, or navigation bar).

Essentially, you want to do both. So in order to migrate your VBA SQL strings into actual stored query objects, you must use QueryDefs. Below is how to iterate to dynamically create the 10 Associates queries and one union query.

Dim qryTopqdef As QueryDef, qryTopUnionqdef As QueryDef, findqdf As QueryDef
Dim i as Integer, j as Integer

' DELETE QUERIES IF EXIST
For each findqdf in CurrentDb.Querydefs
    If Instr(findqdf.Name, "qryTopSQL") > 0 Then
        db.QueryDefs.delete(findqdf.Name)
    End if
Next findqdf

' INDIVIDUAL 10 QUERIES
i = 1
For Each Item In Associates

    qryTopSQL = "SELECT TOP " & QA# & _
            " Date, ID, [L#], Deal, RndNum FROM tbl_Data WHERE Date Between #" & _
            StartDate & "# And #" & EndDate & "# AND ID = " & Item & _
            " ORDER BY RndNum"

    ' QUERY NAMES ARE SUFFIXED BY THE ITERATOR COUNT
    Set qryTopqdef = CurrentDb.CreateQueryDef("qryTopSQL_" & i, qryTopSQL)
    i = i + 1
Next Item


' UNION QUERY
j = 1
For Each Item In Associates
    If j = 1 Then
        qryTopSQL = "SELECT TOP " & QA# & _
                " Date, ID, [L#], Deal, RndNum FROM tbl_Data WHERE Date Between #" & _
                StartDate & "# And #" & EndDate & "# AND ID = " & Item & _
                " ORDER BY RndNum"
    Else
        ' UNIONS ARE SIMPLY STACKS OF SELECT STATEMENTS OF SAME COLUMN NUMBER AND DATA TYPE
        ' TOGETHER JOINED BY THE UNION OR UNION ALL CLAUSE
        qryTopSQL = qryTopSQL & " UNION SELECT TOP " & QA# & _
                " Date, ID, [L#], Deal, RndNum FROM tbl_Data WHERE Date Between #" & _
                StartDate & "# And #" & EndDate & "# AND ID = " & Item & _
                " ORDER BY RndNum"
    End if
    j = j + 1
Next Item

Set qryTopUnionqdef = CurrentDb.CreateQueryDef("qryTopSQLUnion", qryTopSQL)


' UNINTIALIZE OBJECTS
Set qryTopqdef = nothing
Set qryTopUnionqdef = nothing

Also - see this SO post on collections vs arrays

Community
  • 1
  • 1
Parfait
  • 104,375
  • 17
  • 94
  • 125
  • Thanks a lot for this, I understand most of it but I'm getting an error on the qryTopSQL statement: The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect. – msim Feb 13 '15 at 21:18
  • Which qryTopSQL statement? It might have to do with your parameters or the collection `Item`. Do this: 1) comment out the `set qryTopqdef...` and `set qryTopUnionqdef...`, 2) temporarily add `MsgBox qryTopSQL` and 3) re-run your function or routine. See if you see any errors in the 10 select statements in the message box pop ups. – Parfait Feb 13 '15 at 21:55
  • on the individual 10 queries, if I comment out `Set qryTopqdef`, and put the msgbox in, I got a correct msgbox with no errors for the 10 queries. When I put `Set qryTopqdef` back in, and put `Msgbox qryTopSQL` after it in the code, I got the same error. It occurs there. – msim Feb 13 '15 at 22:08
  • The `MsgBox` is a debugging practice not a fix for the code! I need you to **read** the SELECT statements of the message boxes and see if they can create a correct query. Does your parameter values (QA#, StartDate, EndDate, etc.) align correctly? – Parfait Feb 13 '15 at 22:47
  • I know i was just telling you what happened. StartDate and EndDate are right but QA# is 0 instead of 15. The IDs represented by `Item` were all right – msim Feb 13 '15 at 23:01
  • Well then that is your issue: `SELECT TOP 0 ...` is an invalid query statement. Investigate that `QA#` variable. By the way, I don't know how you escaped the compiler but `QA#` is an invalid VBA variable declaration, remove `#`. – Parfait Feb 13 '15 at 23:33
  • Hi, sorry for the delay. I figured out my error with the `QA#`, it now gives me the right number. when I remove the `MsgBox` and uncomment the two `set`s, I get an error `Invalid SQL Statement; expected 'DELETE','INSERT','PROCEDURE','SELECT',or 'UPDATE'`. The yellow highlighter is on the `set qryTopUnionqdef...` part. I'm looking at this and trying things but the union part is still a bit confusing to me. Thanks. – msim Feb 16 '15 at 18:16
  • I guess I'm confused by your If statement for the Union Query. `qryTopString` was never defined, so I'm assuming that both of the If scenarios were supposed to be `qryTopString = ...` but I get a different error when I do that. I feel like I already made the queries, so the first part of the IF is unnecessary? I just need the else part. I'll try this. – msim Feb 16 '15 at 18:25
  • OK I'm very close! I changed the variable name to `qryTopString` like i talked about in my last comment, and there needed to be a space in the `" UNION ALL "` part. So now it at least opens the query. But the query is wrong. It does not union all of them, it just has results similar to the last `item` in collection `Associates`' `qryTopSQL` query. – msim Feb 16 '15 at 19:01
  • Closer still!! see my edit to the question for what I tried and what I'm still having problems with. – msim Feb 16 '15 at 19:25
  • I edited my post. You are correct it should read `qryTopSQL` in the `set qryTopUnionqdef...` command with a space before `UNION`. As for your update, you need to concatenate your string. So change: `qryTopString2 = " UNION SELECT * FROM qryTopSQL_" & k` to `qryTopString2 = qryTopString2 " UNION SELECT * FROM qryTopSQL_" & k`. By the way, do not use `UNION ALL` or you will get duplicates. Use only `UNION` for distinct values. See [here](http://stackoverflow.com/questions/49925/what-is-the-difference-between-union-and-union-all). – Parfait Feb 16 '15 at 22:52