N Top Record Selection Based on Own SQL Statement in MS-Access - sql

I'm re-writing a small ms-access application to take examinations on.
What they want is for the tests to grab a set of random questions based on how large the exam's size is.
If each exam was a set number of questions, I could just stick the number in the TOP statement and be done with it, but there are a variable number of questions for each exam, so I want to replace the constant number next to the TOP with a field from the query.
What I basically want is like this:
SELECT TOP tblExam.[ExamSize] *
FROM tblExamQuestions INNER JOIN tblExam
ON tblExamQuestions.ExamID = tblExam.ExamID
WHERE tblExam.ExamID = 10
ORDER BY Rnd(tblExamQuestions.ExamQuestionID);
I'm supplying the new ExamID to this query for each exam session when I open the report, so this will probably get in the way.
DoCmd.OpenForm strExamName, , , "tblExam.ExamID = " & strExamID

I think you would have to build the query dynamically.
sSQL="SELECT TOP " & DlookUp("ExamSize","tblExam","ExamID = 10") _
& " FROM tblExamQuestions INNER JOIN tblExam " _
& "ON tblExamQuestions.ExamID = tblExam.ExamID " _
& "WHERE tblExam.ExamID = 10 " _
& "ORDER BY Rnd(tblExamQuestions.ExamQuestionID)"
'' Permanently change an existing query
CurrentDB.QueryDefs("MyReportQuery").SQL=sSQL

Related

Only show field value if another field is equal to “X” VBA Acces

Let's say I've got this query containing multiple tables.
Containing this data when run :
I want the query to show me the data exactly as it is in the database but when I run my SQL statement it'll show it as if on the second row the field OpslagLocatie has the same data as the field above it.
Outcome :
My solution :
Me.[Keuzelijst EAN artikel op vooraad].RowSource =
"SELECT TussenMAATenARTKEL.EAN_Code AS [EAN Code], TbOpzoekKleur.Kleur AS Kleur, TbOpzoekVoorraadMaat.VoorraadMaten AS Maat, Sum(Stock.Aantal_per_Lokatie) AS Aantal, TbOpzoekVoorraadLocatie.VoorraadLocatie AS Lokatie, Stock.ArtikelDetail_ID AS Detail, IIf([TussenMAATenARTKEL].[Opslaglocatie], [Stock].[VoorraadLocatie_ID]=8,[TussenMAATenARTKEL].[OpslagLocatie]) AS [Opslag Locatie] " & _
"FROM (TbOpzoekVoorraadMaat RIGHT JOIN (TbOpzoekKleur RIGHT JOIN TussenMAATenARTKEL ON TbOpzoekKleur.ColorCode = TussenMAATenARTKEL.Colorcode) ON TbOpzoekVoorraadMaat.VoorraadNummer = TussenMAATenARTKEL.VoorraadNummer) RIGHT JOIN (TbOpzoekVoorraadLocatie RIGHT JOIN Stock ON TbOpzoekVoorraadLocatie.VoorraadLocatie_ID = Stock.VoorraadLocatie_ID) ON TussenMAATenARTKEL.ArtikelDetail_ID = Stock.ArtikelDetail_ID " & _
"GROUP BY TussenMAATenARTKEL.EAN_Code, TbOpzoekKleur.Kleur, TbOpzoekVoorraadMaat.VoorraadMaten, TbOpzoekVoorraadLocatie.VoorraadLocatie, Stock.ArtikelDetail_ID, Stock.VoorraadLocatie_ID, TussenMAATenARTKEL.Artikel_ID, TussenMAATenARTKEL.OpslagLocatie " & _
"HAVING (((Sum(Stock.Aantal_per_Lokatie)) <> 0) And ((TussenMAATenARTKEL.Artikel_ID) = " & test & ")) " & _
"ORDER BY TbOpzoekVoorraadMaat.VoorraadMaten;"
Outcome after updating my code with an iif statement :
After running my code the field TussenMAATenARTKEL.OpslagLocatie only shows the values -1 or 0. I expect it to show or not show the OpslagLocatie instead of -1 and 0.
What am I doing wrong?
That's because your OpslagLocatie is a lookup field.
So, in your query, join and include the table and the field in this from where OpslagLocatie looks up the code KBA-ACC.

MS Access VBA SQL SELECT * INTO tempTbl WHERE Stuff="" AND OtherStuff BETWEEN Date Range

I have a form with one text box, two combo boxes (dropdowns), and two text boxes with input masks for mm/dd/yyyy 99/99/0000;0;_
I am attempting to use all of these fields as filters for a subform.
I have the controls set to fire after update and run a sub that builds a SELECT * INTO sql string for a temp Table that is then sourceobject'ed back to the subform.
In code I have for each control I have code building a snippet of the Where statement for the final sql. the snippet grows as needed, is labeled "Filter"
Some other non-Finished Code....
If Not IsNull(txtDateFrom) Then
If i > 1 Then Filter = Filter & " AND " & "([Date_LastSaved] >= " & Me.txtDateFrom & ")" & " And " & "([Date_LastSaved] <= " & Me.txtDateTo & ")"
End If
Dim sql As String
sql = "SELECT * INTO tmpTable FROM tblReview"
If Not IsNull(Filter) Then
sql = sql & " WHERE " & Filter
End If
My issue and question is that I am testing this one specific situation where there will be Filter = Filter & " AND " & "DATE_STUFF"
where the final sql looks like...
SELECT * INTO tmpTable FROM tblReview WHERE ReviewStatus = 'Quoted' AND ([Date_LastSaved] >= 09/12/2018) And ([Date_LastSaved] <= 10/16/2018)
which should have some result with the test data. Yet, the tmpTable is empty.
This is only happening when I apply a date range criteria.
I tried BETWEEN but could not nail down the syntax.
Any insight is greatly appreciated, Thanks!
UPDATE:
Answer:
If i > 1 Then Filter = Filter & " AND " & "([Date_LastSaved] >= #" & Me.txtDateFrom & "#)" & " And " & "([Date_LastSaved] <= #" & Me.txtDateTo & "#)"
If you want to use dates then they must be quoted. If you just say 10/16/2018 then you are dividing the integer 10 by 16 by 2018 which will yield an integer zero. It will then convert the dates to an integer to do the compare, which will yield a much bigger number, and thus you get no rows.
Any date testing should always be done using date types rather than strings. I think in msaccess you can surround it in #, but not sure. Just research this.

SQL Server Join Tables By Combining 2 Columns

This sounds ridiculously easy but I've tried so many different approaches. This query is just set up weird and I'm trying to JOIN it but there's not a common column I can do that with. There is, however, a LastFirst column (consists of LastName then FirstName) written in the context of DOE, JOHN. Then on the columns I'm trying to join that with it's just FirstName (John) and LastName (Doe).
I'm actually trying to select data from 4 tables that all are returning 1 row. These 2 tables can be joined:
SELECT
RIFQuery.*,
_Employee.EmployeeLastName + ', ' + _Employee.EmployeeFirstName AS EmployeeLastFirst,
_Employee.EmployeeTitle, _Employee.Phone As EmployeePhone,
_Employee.EmailAddress As EmployeeEmailAddress
FROM
RIFQuery
INNER JOIN
_Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE
RIFQuery.Autonumber = 1
This one has nothing to join with so I'll probably union it and null remaining columns:
SELECT *
FROM tblOrganization
This is the table that contains LastName and FirstName that I'm trying to join with RIFQuery.LastFirst:
SELECT
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM
_Clients
WHERE
_Clients.LASTNAME = left(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst)))
AND _Clients.FIRSTNAME = ltrim(substring(RIFQuery.LastFirst, len(RIFQuery.LastFirst)-CHARINDEX(',', REVERSE(RIFQuery.LastFirst))+2, len(RIFQuery.LastFirst)))
In that WHERE statement the code will split the LastFirst column and get the row by searching their LastName and FirstName. I'm wondering if there's a way I can write that into a JOIN? Otherwise I can probably UNION and null remaining columns but it will look very ugly.
UPDATE
I tried 2 suggestions from here and both result in a syntax error. I forgot to mention that I'm executing this code inside Microsoft Access VBA and trying to retrieve a DAO.RecordSet. I had to remove some table names in the SELECT statement to get past a syntax error from there, so maybe I should update the question to reflect MS ACCESS and not SQL Server, although only the query is the only pure Access object and the rest are linked ODBC tables to SQL Server.
UPDATE
Just one of those issues where I can't sleep until it's fixed and will obsess until it is. If I take out all _Employee references (from SELECT and JOIN statements), it wants to work but errors about too few parameters. I just now know this is related to _Employee. Getting different results from applying parentheses and just hoping I'll get lucky and hit on it.
The error is caused by this line:
INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy]
I get this error:
"Syntax error (missing operator) in query expression".
As seen in this screenshot:
Here's my latest query I'm playing with, minus the parentheses:
str = "SELECT [RIFQuery].*, " & vbCrLf & _
" ([_Employee].[EmployeeLastName] & ', ' & [_Employee].[EmployeeFirstName]) AS [EmployeeLastFirst], " & vbCrLf & _
" [_Employee].[EmployeeTitle], " & vbCrLf & _
" [_Employee].[Phone] AS [EmployeePhone], " & vbCrLf & _
" [_Employee].[EmailAddress] AS [EmployeeEmailAddress], " & vbCrLf & _
" [_Clients].[Gender] AS [ClientGender], " & vbCrLf & _
" [_Clients].[DOB] AS [ClientDOB], " & vbCrLf & _
" [_Clients].[SSN] AS [ClientSSN] " & vbCrLf & _
"FROM [_Clients] " & vbCrLf & _
" INNER JOIN [RIFQuery] ON [RIFQuery].[LastFirst] = [_Clients].[LASTNAME] & ', ' & [_Clients].[FIRSTNAME] " & vbCrLf & _
" INNER JOIN [_Employee] ON [_Employee].[AutoNumber] = [RIFQuery].[CreatedBy] " & vbCrLf & _
"WHERE [RIFQuery].[Autonumber] = 1;"
For debugging purposes, if I remove those last 2 lines and the _Employee SELECT statements, it'll process the query without a problem. If anyone has any ideas just let me know.
I was focused on that RIFQuery JOIN statement being the culprit for the longest time but I've found that simply is not the issue any more. With that said, this thread has been essentially solved and I appreciate the help.
MS Access is using a slightly different syntax than SQL Server when it comes to using more than one JOIN. You could leave out the JOIN with the _Clients (making it a cross join) and move that condition to the WHERE clause, which would make the query look like this (and which would allow you to display the design window for the query without any problem)
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME;
Instead of assembling the query string in VBA just for being able to change the parameter value, I suggest to save the following query as an Access object (maybe qryRIF):
PARAMETERS lgRIF Long;
SELECT RIFQuery.*,
EmployeeLastName + ', ' + EmployeeFirstName As EmployeeLastFirst,
EmployeeTitle, Phone As EmployeePhone, EmailAddress As EmployeeEmailAddress,
Gender As ClientGender, DOB As ClientDOB, SSN As ClientSSN
FROM _Clients, RIFQuery INNER JOIN _Employee ON RIFQuery.CreatedBy = _Employee.AutoNumber
WHERE RIFQuery.LastFirst = _Clients.LASTNAME & ", " & _Clients.FIRSTNAME
AND RIFQuery.Autonumber = [lgRIF];
In your VBA code, you can use code like the following to grab the QueryDef object, assign the parameter value and open a recordset:
With CurrentDb.QueryDefs!qryRIF
!lgRIF = lgRIF
With .OpenRecordset()
' ... your code ...
.Close
End With
.Close
End With

T-SQL - Filtering records based on a date

I am writing SQL Server queries and need a solution for how to filter the rows that are returned properly.
The basic setup is as follows - I am selecting a bunch of records from a table based primarily on an identifier. So, for a given identifier there might be 100 records that are returned initially. Within these 100 records, however, there are a number of them that need to be deleted - not because they are duplicates, but because one is newer than the other. So I essentially just need a way to further filter the results based on whichever record was created/modified most recently.
I know that ideally, these "old" records should not be in the database, but I don't have control over that. What is happening is essentially people are updating the entries over time to reflect new information, but rather than editing the "old" entry, a new one gets entered each time. Thus, there might be 3 entries for a given identifier, but I only need the one that was most recently entered.
Is there an easy way to do this in the T-SQL query string? It would be similar to the "Last of" function in Access queries. I do have a properly formatted date column for each record.
Thanks!
My query string so far (excuse the VB syntax):
"SELECT *" & _
"FROM Performance_Override " & _
"WHERE ([Deal_Name] = " & "'" & Range("ID").value & "'" & " or" & _
" [UNIQUE_ID] LIKE " & "'" & "%SPLIT_LOAN%" & "')" & " AND" & _
" ([Scenario] = " & "'" & "BASE" & "')" & _
"ORDER BY [Date] ASC; "
Select is
select ID, max(datefield)
from table
group by ID
Do you just need a select or do you want to actually delete the old entries?
WITH TableTop AS
(
SELECT ID, User, OrderDate
ROW_NUMBER() OVER (ID BY OrderDate DESC) AS RowNumber
FROM Table
)
SELECT ID, User, OrderDate
FROM TableTop
WHERE RowNumber = 1;

How to "order by" a column and "Include Column Name with query"?

I am trying to run a sql query in excel and I want to :
1. order the query result by my column "Stationname"
2. include the column names with the query
Right now it is returning all the columns without the column name, and the end users do not know what it is.
Could someone please help? I am stuck! Below is my current code:
strQuery = "select pipelineflow.lciid lciid, ldate, volume, capacity, status, " & _
"pipeline, station, stationname, drn, state, county, owneroperator, companycode, " & _
"pointcode, pointtypeind, flowdirection, pointname, facilitytype, pointlocator, " & _
"pidgridcode from pipelineflow, pipelineproperties " & _
"where pipelineflow.lciid = pipelineproperties.lciid " & _
"and pipelineflow.audit_active = 1 " & _
"and pipelineproperties.audit_active =1 " &
_
"and pipelineflow.ldate " & dtInDate & _
"and pipelineproperties.stationname = '" & Stationname & "' "
For part 1 of your question, add an ORDER BY clause to your query. In this case: order by stationname
Part 2: Not sure why column names aren't being included in your query. You can explicitly name a column using something like the following (purely an example):
select mycolumn as "MyCustomizedColumnName" from mytable
That allows you to give columns names of your choosing. Having said that, you shouldn't be required to do so for every column, so I suspect something else is going on in your case.
I should probably add that a stored procedure (rather than dynamic SQL) will yield better runtime performance.
For ordering just put
Order By stationname
at the end of the Query.
You can iterate through the column names by using:
rst(1).Name
where rst is your recordset, and the number is the index of the column.
To sort your query results , use 'ORDER BY' at the end of the query. The last lines of your query would look like this
"and pipelineproperties.stationname = '" & Stationname & "' " & _
"ORDER BY pipelineproperties.stationname"
The column heading are returned in your query data, but not automatically written to the Excel worksheet. The code snippet below shows how to loop through the recordset's column headings and write them to the active cell's row.
'rst' refers to your recordset, update the name as required.
If Not rst.EOF Then
For x = 0 To rst.Fields.Count - 1
With ActiveCell.Offset(0, lcount)
.Value = rst.Fields(x).Name
End With
Next
End If
Make sure that you offset down from the active cell when writing the query results to the worksheet, otherwise your headings will be overwritten by the data.
Activecell.Offset(1,0).CopyFromRecordset rst