Group By/Distinct in Access 2007 - group-by

I have a query in which I select multiple columns, but only need the results to return a distinct set of data:
Dim strSQL As String
strSQL = "SELECT REQUIRED_TOOLS.REQUIRED_TOOL_NSN, REQUIRED_TOOLS.REQUIRED_TOOL_NAME, REQUIRED_TOOLS.ID, OEM_MASTER.OEM_No, REQUIRED_TOOLS.IS_TEST_EQUIP, OEM_MASTER.OEM_IN_INVENTORY, AIRCRAFT_EQUIPMENT.ID"
strSQL = strSQL & " FROM (OEM_MASTER INNER JOIN (REQUIRED_TOOLS INNER JOIN REL_OEM_TO_NSN ON REQUIRED_TOOLS.ID = REL_OEM_TO_NSN.NSN_REF_ID) ON OEM_MASTER.ID = REL_OEM_TO_NSN.OEM_REF_ID) INNER JOIN (AIRCRAFT_EQUIPMENT INNER JOIN REL_AC_EQUIP_TO_TOOLS ON AIRCRAFT_EQUIPMENT.ID = REL_AC_EQUIP_TO_TOOLS.AC_EQUIP_ID) ON REQUIRED_TOOLS.ID = REL_AC_EQUIP_TO_TOOLS.TOOL_ID"
strSQL = strSQL & " WHERE (((REQUIRED_TOOLS.IS_TEST_EQUIP)=No) AND ((OEM_MASTER.OEM_IN_INVENTORY)=Yes) AND ((AIRCRAFT_EQUIPMENT.ID)=" & Me.List0.Column(2) & "))"
strSQL = strSQL & " GROUP BY REQUIRED_TOOLS.REQUIRED_TOOL_NAME"
Me.List1.RowSource = strSQ
When I comment out the group by clause, I get results, but multiple results of REQUIRED_TOOL_NAME (which only exist in its own table once, but can have multiple OEM_MASTER.OEM_No references in the OEM_MASTER.OEM_No table/column). I need to filter out all repeat instances in my list.
Thanks.

Related

Is it possible to add sql functions to an sql query?

I need to concatenate the result of a subquery in a file based model (i.e. with ms access) and following the suggestions I found here, I could define a function to use in the query.
I try that in the SQL scratch pad but nothing happens...
Function Coalsce(strSQL As String, strDelim, ParamArray NameList() As Variant)
Dim db As Database
Dim rs As DAO.Recordset
Dim strList As String
Set db = CurrentDb
If strSQL <> "" Then
Set rs = db.OpenRecordset(strSQL)
Do While Not rs.EOF
strList = strList & strDelim & rs.Fields(0)
rs.MoveNext
Loop
strList = Mid(strList, Len(strDelim))
Else
strList = Join(NameList, strDelim)
End If
Coalsce = strList
End Function
select switch(Coalsce(SELECT DISTINCT ', ' + obj_phase2.name as [text()]
FROM ((((t_object obj_ds2
INNER JOIN t_connector co2
ON (obj_ds2.object_id = co2.start_object_id))
INNER JOIN t_object obj_adu2
ON (co2.end_object_id = obj_adu2.object_id
AND obj_adu2.Stereotype='EUM_ADU'))
LEFT JOIN t_object obj_prx2
ON (obj_prx2.Classifier_guid = co2.ea_guid))
LEFT JOIN t_connector pc2
ON (obj_prx2.Object_ID = pc2.Start_Object_ID AND pc2.Stereotype = 'trace'))
LEFT JOIN t_object obj_phase2
ON (pc2.End_Object_ID = obj_phase2.object_id)
WHERE obj_ds2.Stereotype = 'EUM_Data-Stream' AND obj_ds2.Object_ID = 13919)='', '',
1=1, 'teste') as [test]
from t_object
Is this possible?
No. EA only allows SELECT statements in the scratchpad. EA is doing some black magic with the SQL before sending it to the database. Misty and obscure that is. But for sure you can not send VB code (or any other advanced stuff) through the pad.
If you want to get the above working you need to place the VB code in a script calling the SELECT via repository.SQLQuery.
It would probably be possible to run such stuff via a native ODBC or driver connection. However, I would absolutely not recommend doing that. I wouldn't do that myself and I've done a lot of strange things with EA.

Access pass-through query with parameters not updating with prompted parameters

An Access pass-through query works when using the default parameters. When used in an Access report, the prompts that are used returns records based on the default parameters in the ptq and not the answered prompts. Default data is being returned.
I have a SQL Server based stored procedure that works, uspWorkCentreReport, that uses #TheDate DATE, #WC VARCHAR(15), #Shift INT for parameters and returns, through a SELECT statement, these columns:
[JOB NUMBER], [REL #], [JOB NAME], QTY.
Here's the ALTER line of the stored procedure code:
ALTER PROCEDURE [dbo].[uspWorkCentreReport]
#TheDate DATE,
#WC VARCHAR(15),
#Shift INT
The Access pass-through query, ptq_uspWorkCentreReport, passes these default parameters '2019-05-30','PCOT',1 and uses a DSN-less ODBC connection that works to return default data. I forgot to try but I think it will return correct data with whatever default parameters I use to replace '2019-05-30','PCOT',1. EDIT - I tried it this morning and indeed any appropriate replacement parameters return the appropriate associated records. Here's the ptq's one line:
exec uspWorkCentreReport '2019-05-30','PCOT',1
I provide the ptq with default parameters based on Albert D. Kallal's SO reply.
I use an Access select query, qry_ptq_uspWorkCentreReport, to receive [JOB NUMBER],[REL #],[JOB NAME],QTY and pass the parameters TheDate, set to Date With Time, WC, set to Short Text, and Shift, set to Integer.
qry_ptq_uspWorkCentreReport uses the pass-through query. The parameters are set using Access' Parameters applet and not within the query fields. Running this select query prompts for the 3 parameters but only returns data based on the default parameters set in the ptq's one line. I did not think to look at the Access SQL statement but will do so when I get to work tomorrow morning. EDIT - Here's the SQL statement for qry_ptq_uspWorkCentreReport:
PARAMETERS TheDate DateTime, WC Text ( 255 ), Shift Short;
SELECT ptq_uspWorkCentreReport.[JOB NUMBER], ptq_uspWorkCentreReport.[REL #], ptq_uspWorkCentreReport.[JOB NAME], ptq_uspWorkCentreReport.QTY
FROM ptq_uspWorkCentreReport;
Of course the above three functions culminate in an Access report, rpt_qry_ptq_WorkCentreReport to make the records human readable.
I have used the same scenario for another report the takes From and To dates as parameters. When that report runs, the prompts take the dates and return records based on those dates and not the dates in the ptq. Here's that ptq:
exec uspMergeAandPJobs '2018-01-01','2019-01-01'
Indeed, I tried using
exec uspMergeAandPJobs '',''
And the report returns 0 records!
Not sure what I am missing and would appreciate any feedback. TIA.
I tried the following with the help of a tutor:
Sub Report_Load()
Dim strFromDate As String
Dim strToDate As String
Dim strWC As String
Dim intShift As Integer
Dim strSQL As String
strFromDate = InputBox("From Date and Time: ")
strToDate = InputBox("Enter To Date and Time: ")
strWC = InputBox("Enter Work Center: ")
intShift = InputBox("Enter Shift: ")
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("")
qdf.SQL = "exec dbo.uspWorkCentreReport " & "'" & strFromDate & "', " & "'" & strToDate & "', " & "'" & strWC & "', " & intShift & ";"
qdf.Connect = "ODBC;DRIVER=ODBC Driver 13 for SQL Server;SERVER=OURS\NTSQL;Trusted_Connection=Yes;DATABASE=TablesCoE;ApplicationIntent=READONLY;"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset
rst.Close
Set rst = Nothing
Set qdf = Nothing
End Sub
After the prompts VBA spits up a Run-Time error 3129 - Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'. Neither of us were able to determine what was causing the error. In VBA the "qdf.SQL..." line is highlighted in yellow.
EDIT - Adding stored proc's SQL code:
ALTER PROCEDURE [dbo].[uspWorkCentreReport_TEST] #FromDate DATETIME,#ToDate DATETIME,#WC VARCHAR(15),#Shift INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Build table variable SumTable structure
DECLARE #SumTable TABLE(matl_nbr VARCHAR(60),QTY DECIMAL(4,0),matl_dsc VARCHAR(50))
-- P jobs and their summed WorkCentre traversals using crosstab - each traversal is added up
INSERT INTO #SumTable(matl_nbr,matl_dsc,QTY)
SELECT SRC1.matl_nbr,SRC1.matl_dsc,
SUM(CASE WHEN SRC1.locn_to = #WC THEN 1 ELSE 0 END) AS QTY
FROM
(
SELECT matl_nbr,matl_dsc,locn_to
FROM mtrk_CompanyE.dbo.trxn_hstd th
WHERE (last_upd >= #FromDate AND last_upd <= #ToDate) AND
locn_to = #WC
)SRC1
GROUP BY matl_nbr,matl_dsc
-- These updates take all the summed WorkCentre (locn_to) columns and turn each into "1" for later summing
UPDATE #SumTable
SET QTY = 1
WHERE QTY >1
-- Shortening the material number from 123456_00_00_R1_00 to 1234560
UPDATE #SumTable
SET matl_nbr = LEFT(matl_nbr,6) + right(LEFT(matl_nbr,9),1)
SELECT LEFT(A.matl_nbr,6)[JOB NUMBER],SUBSTRING(A.matl_nbr,7,1)[REL #],matl_dsc AS [JOB NAME],QTY
FROM (SELECT matl_nbr,matl_dsc,
SUM(CASE WHEN QTY = 1 THEN 1 ELSE NULL END) AS QTY
FROM #SumTable
GROUP BY matl_nbr,matl_dsc)A
ORDER BY QTY DESC;
END
EDIT - Finished sub:
Private Sub Report_Open(Cancel As Integer)
Dim strFromDate As String
Dim strToDate As String
Dim strWC As String
Dim intShift As Integer
Dim strSQL As String
strFromDate = InputBox("Enter From Date and Time: ")
strToDate = InputBox("Enter To Date and Time: ")
strWC = InputBox("Enter Work Center: ")
intShift = InputBox("Enter Shift: ")
strSQL = "exec dbo.uspWorkCentreReport_TEST " & "'" & strFromDate & "', " & "'" & strToDate & "', " & "'" & strWC & "', " & intShift & ";"
CurrentDb.QueryDefs("ptq_uspWorkCentreReport").SQL = strSQL
DoCmd.OpenReport "rpt_qry_ptq_uspWorkCentreReport", acViewReport
Me.lblFromDate.Caption = strFromDate
Me.lblToDate.Caption = strToDate
Me.lblWC.Caption = strWC
Me.lblShift.Caption = intShift
End Sub
Your Access query has parameters:
PARAMETERS TheDate DateTime, WC Text ( 255 ), Shift Short;
and since they are defined in the query definition, Access asks for them when opening/running the query.
But these parameters are never used!
There is no way for Access to pass these parameters into the pass-through query that is the basis of the Access query. Again, a PT query is nothing more than a Connect string and a constant SQL string.
So when you run the Access query, it will always run the saved contents of the PT query, i.e.
exec uspWorkCentreReport '2019-05-30','PCOT',1
The parameters you entered are ignored.
What you need to do (as outlined in the answer you refer to):
create a form to collect the parameter values
dynamically create the SQL string for the PT query with VBA
assign that SQL to the PT query:
CurrentDb.QueryDefs("ptq_uspWorkCentreReport").SQL = strSql
(it is automatically saved)
and then you can run the report based on the Access query - or better: directly use the PT query as record source for the report.
Remove the parameters from the Access query, they are of no use for your situation. Or remove the query entirely, unless you need it to join the PT query with something else.
Edit for above edit:
If you get a runtime error, there is probably a syntax error in your .Sql. Build the SQL string in a variable, do Debug.Print strSql, and run that string in SSMS. You may need to change date formatting (depending on your locale settings).
Also: See my 3rd bullet. Defining a temporary querydef and opening a recordset doesn't work for a report. You must assign the .Sql of the existing query that is the record source of the report.
Addendum: if you need to create a new query, first set .Connect, and then .Sql, so Access knows it's a Pass-Through query.
Access SQL doesn't know exec.
Edit 2
You have an existing, working PT query ptq_uspWorkCentreReport, which returns records for one set of parameters, e.g.
exec uspWorkCentreReport '2019-05-30','PCOT',1
Use this query as record source for your report.
To run the report with different parameters, you must modify the query's SQL. You can do this manually in query design view, or with VBA.
I think Report_Load() is too late for modifying its record source (the PT query). Run the following sub, then open the Report.
Sub SetUspParameters()
Dim strFromDate As String
Dim strToDate As String
Dim strWC As String
Dim intShift As Integer
Dim strSQL As String
strFromDate = InputBox("From Date and Time: ")
strToDate = InputBox("Enter To Date and Time: ")
strWC = InputBox("Enter Work Center: ")
intShift = InputBox("Enter Shift: ")
strSQL = "exec dbo.uspWorkCentreReport " & "'" & strFromDate & "', " & "'" & strToDate & "', " & "'" & strWC & "', " & intShift & ";"
Debug.Print strSQL
' This line is all that's needed to modify the PT query
CurrentDb.QueryDefs("ptq_uspWorkCentreReport").SQL = strSQL
End Sub
In practice, you don't want to use 4 x InputBox, but a form.

Run SQL query on each item in multiselect listbox and show results in another listbox?

I'm running a "select distinct" query on fields selected in a multiselect listbox (the listbox is populated with fields from a table). The code worked fine before I made it multiselect, and now the SQL query is not functioning. For example when I select the fields "Gender" and "INTERFACE" from the field list, the results in the 2nd list box are:
SELECT DISTINCT
Gender
INTERFACE
Ideally my results would include the field name and then the values, with a line between each field results.
Here is my code:
Dim strSQL As String
Dim strCriteria As String
Dim varItem As Variant
On Error GoTo Err_Command206_Click
For Each varItem In Me.ScrubbedList.ItemsSelected
strCriteria = strCriteria & ",[" & Me!ScrubbedList.ItemData(varItem) & "]"
Next varItem
strSQL = "SELECT DISTINCT " & Mid(strCriteria, 2) & " FROM Scrubbed"
'====== Testing
Debug.Print strSQL
'=====
Me.List316.RowSource = strSQL
Exit_Command206_Click:
Exit Sub
Err_Command206_Click:
MsgBox "Please select a field"
You seem to have some things in the wrong place:
Dim strSQL As String
Dim strCriteria As String
Dim varItem As Variant
On Error GoTo Err_Command206_Click
For Each varItem In Me.ScrubbedList.ItemsSelected
strCriteria = strCriteria & ",[" & Me!ScrubbedList.ItemData(varItem) & "]"
Next varItem
strSQL = "SELECT DISTINCT " & Mid(strCriteria,2) & " FROM Scrubbed"
'====== Testing
Debug.Print strSQL
'======
Me.List316.RowSource = strSQL
Exit_Command206_Click:
Exit Sub
Err_Command206_Click:
MsgBox "Please select a field"

Loop through recordset to populate listbox with results of SQL query?

I have a multi-select listbox which I want to be the source of a sql query with results displayed in a listbox. Currently I have the results going to a recordset which is displayed beautifully when only one 1 field is selected. For instance, if the user selects Gender, no recordset datasheet opens and List20 shows the field name, underscored, with the distinct values below it--Perfect!! When I try to select more than one item things go awry. For instance 2 items selected (Gender, Interface) will result in Gender (underlined) but with 2 F's and 2 M's below it and none of the Interface field values. How do I loop through each selection and have them show in the listbox? Here is my code. Also, weirdly, List13 shows no results when I run the query, but when I take away the line:
Set Me.List13.Recordset = rs
a recordset datasheet opens up and the desired results no longer appear in List20. Please help!
Private Sub Command19_Click()
Dim strSQL As String
Dim strCriteria As String
Dim varItem As Variant
Dim dbs As Database
Set dbs = CurrentDb()
Dim qdf As QueryDef
Dim rs As Recordset
On Error GoTo Err_Command19_Click
For Each varItem In Me!List101.ItemsSelected
strCriteria = strCriteria & ",'" & Me!List101.ItemData(varItem) & "'"
Next varItem
strCriteria = Right(strCriteria, Len(strCriteria) - 1)
strSQL = "SELECT DISTINCT " & strCriteria & " FROM Scrubbed"
strSQL = Replace(strSQL, "'", "")
Set rs = dbs.OpenRecordset(strSQL)
Do Until rs.EOF
Set Me.List20.Recordset = rs
Set Me.List13.Recordset = rs
Loop
With dbs
Set qdf = .CreateQueryDef("TmpDistinctValues", strSQL)
DoCmd.OpenQuery "TmpDistinctValues"
.QueryDefs.Delete "TmpDistinctValues"
End With
dbs.Close
qdf.Close
Exit_Command19_Click:
Exit Sub
Err_Command19_Click:
MsgBox "Please select a field"
End Sub
Surely you mean:
For Each varItem In Me!List101.ItemsSelected
strCriteria = strCriteria & "," & Me!List101.ItemData(varItem)
colcount = colcount + 1
colwidths = colwidths & ";" & "1134"
Next varItem
strCriteria = Right(strCriteria, Len(strCriteria) - 1)
strSQL = "SELECT DISTINCT " & strCriteria & " FROM Scrubbed"
''strSQL = Replace(strSQL, "'", "")
''Set rs = dbs.OpenRecordset(strSQL)
''Do Until rs.EOF
Me.List20.RowSource = strSQL
Me.List20.ColumnCount = colcount
Me.List20.ColumnWidths = Mid(colwidths, 2)
''Set Me.List13.Recordset = rs
''Loop

How do I display a count of null values for field selected in combobox?

I've tried using DCOUNT and SQL and nothing is working. I've pasted both queries below. When I run the SQL nothing appears in the listbox. When I run the DLOOKUP I get the error message "Run-time error '2001": You canceled the previous operation. The combobox name is ScrubbedList. Table is named Scrubbed.
DCOUNT
Dim strScrubbedValue As String
strScrubbedValue = Me.ScrubbedList
Dim intCountNull As Integer
intCountNull = DCount("*", "Scrubbed", "IsNull" & strScrubbedValue)
Text267 = intCountNull
SQL
Dim strSQL As String
Dim strScrubbedValue As String
strScrubbedValue = Me.ScrubbedList
strSQL = "SELECT Count(*) As CountAll" & strScrubbedValue & " FROM Scrubbed"
strSQL = strSQL + "WHERE" & strScrubbedValue = ""
Me.List265.RowSource = strSQL
Try:
intCountNull = DCount("*", "Scrubbed", "SomeField Is Null")
So for the combo:
intCountNull = DCount("*", "Scrubbed", strScrubbedValue & " Is Null")
It is important to ensure that you have included relevant spaces when concatenating strings.
Dim strSQL As String
Dim strScrubbedValue As String
strScrubbedValue = Me.ScrubbedList
strSQL = "SELECT Count(*) As CountAll " & strScrubbedValue & " FROM Scrubbed"
strSQL = strSQL & " WHERE " & strScrubbedValue & " Is Null"
Me.List265.RowSource = strSQL
Note that Null and zero-length strings (ZLS) are not the same.
To get both, you can say:
strSQL = strSQL & " WHERE " & strScrubbedValue & " & '' = ''"
The string concatenator in VBA is &, not +. The plus sign must be used with care, because it can lead to unexpected nulls.