VBScript Excel ADO connection: Get value using column alias in SQL query - sql

In following code, I can get the count from excel using
objTempRecordset.Fields.Item(0).Value
However, I want to use column name alias in SQL.
i.e.
sSQL = "Select Count(*) AS RecCount FROM [NELimits$] A WHERE A.Type = 'A' AND A.ID = " &Chr(39) & "R001" & Chr(39)
and I want to get the result using:
objTempRecordset.Fields.Item("RecCount").Value
I also tried objTempRecordset.Fields.Item("_Count(*)_").Value but no luck
Can someone please let me know how to use column name alias in this case?
Note: Excel has 2 columns
ID: with values such as "R001", "R002"
Type: with values such as "A","B","C"
Sample code:
sSQL = "Select Count(*) FROM [NELimits$] A WHERE A.Type = 'A' AND A.ID = " &Chr(39) & "R003" & Chr(39)
Sqlquery = sSQL
sFilePath = "C:\Temp\DataSheet.xlsx"
Dim objTempConnection : Set objTempConnection = CreateObject("ADODB.Connection")
Dim objTempRecordSet : Set objTempRecordSet = CreateObject("ADODB.Recordset")
Dim strPath
'Define constants for objTempRecordset
Const adOpenStatic=3
Const adLockOptimistic=3
Const adLockPessimistic=2
Const adCmdText = &H001
'Open connection
objTempConnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="& sFilePath &";Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
objTempRecordset.ActiveConnection = objTempConnection
objTempRecordset.CursorType = adOpenStatic
objTempRecordset.LockType = adLockOptimistic
objTempRecordset.Open Sqlquery
If objTempRecordset.EOF Or objTempRecordset.BOF Then
msgbox "no record"
End If
msgbox "Record Count: "&objTempRecordset.RecordCount
msgbox "Value:" & objTempRecordset.Fields.Item(0).Value

With the ACE SQL engine (used here in querying workbook), original field names, column aliases, or table names with spaces, special characters (non-alphanumeric), or reserved words need to be wrapped in square brackets or backticks to properly escape them.
Spaces
sSQL = "Select Count(*) AS [Rec Count] FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
sSQL = "Select Count(*) AS `Rec Count` FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
Special Characters (e.g., hyphen and pound/hashtag sign)
sSQL = "Select Count(*) AS [Rec-Count] FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
sSQL = "Select Count(*) AS `Rec-Count` FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
sSQL = "Select Count(*) AS [Rec#] FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
sSQL = "Select Count(*) AS `Rec#` FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
Reserved words (e.g., Count)
sSQL = "Select Count(*) AS [Count] FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
sSQL = "Select Count(*) AS `Count` FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
Otherwise, any field name or column alias is legitimate in query and can be read in record set in following formats:
objTempRecordset.Fields.Item(0).Value ' BY INDEX IN ITEM '
objTempRecordset.Fields.Item("Rec Count").Value ' BY NAME IN ITEM '
objTempRecordset.Fields("Rec Count").Value ' BY NAME IN FIELD COLLECTION '
objTempRecordset![Rec Count].Value ' BY NAME (EXCLAMATION POINT QUALIFIER) '
Furthermore, missing column aliases are handled in a special manner with ACE:
Missing Alias on Query Expression (e.g., Count function aggregation)
sSQL = "Select Count(*) FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
Missing Alias on Duplicate Field
sSQL = "Select ID, ID FROM [NELimits$] A" _
& " WHERE A.Type = 'A' AND A.ID = 'R003'"
For above two missing aliases, the ACE engine creates a column alias usually starting at Expr1 (inside MS Access -the usual interface to the ACE Engine) or Expr1000 for ODBC connections and incrementing for all other unnamed expressions or unnamed duplicate field references.

Related

Instead of 'table variable+column name =' is there any method to simplify that?

Instead of table variable+column name = is there any method to simplify that?
update [hopi].[dbo].[hdc
set dostat = 'i'
from [hopi].[dbo].[hdc] as b
inner join [hopi].[dbo].hperson as a
on b.hpercode = a.hpercode
inner join [hopi].[dbo].[hprocm] as c
on b.proccode = c.proccode
where b.dostat = 'a'
and datepart(yy,b.dodate)='" & yr & "'
and datepart(mm,b.dodate)='" & mnth & "'
and datepart(dd,b.dodate)='" & dy & "'
and a.last= '" & & "'enter code here
and a.first= '" & & "'
and (c.procdesc='prec' or c.procdesc='pros' or c.procdesc='vat' or c.procdesc='vet' or c.procdesc='pak' or c.procdesc='pren' or c.procdesc='maser' or c.procdesc='lolo' or c.procdesc='yawa')
You can use an IN clause here to avoid the repetition i.e.
AND (c.procdesc IN ('prec', 'pros', 'vat', 'vet', 'pak', 'pren', 'maser', 'lolo', 'yawa'))

Is there a way to combine all the outputs into one in MS-ACCES?

I want to make a SQL Filter in MS-Acces where I have the Option to filter all the Elements in the table. But when I make the UNION SELECT, I can show only 1 column in each row, so I made database_geräte.* to database_geräte.ID .
This works fine now, but I want all the Outputs from the database_geräte.ID select into one row, so that I can Filter all of them at once.
I tried to make a GROUPCONCAT, but that gives me an error.
SELECT database_geräte.ID, dbo.GROUPCONCAT (STRINGVALUE) FROM database_geräte
UNION
SELECT database_geräte.Gerät FROM database_geräte;
I also tried to make a count on the
database_geräte.ID
But then I get the value of the database_geräte.ID select, which doesn't fit in the filter because a ID with that number doesn't exist...
The SQL Select:
SELECT database_geräte.ID, dbo.GROUPCONCAT FROM database_geräte
UNION
SELECT database_geräte.Gerät FROM database_geräte;
The SQL filter in VBA:
sql = "SELECT* FROM database1 WHERE Gerät = '" & Me.GeräteFilter & "'"
Me.sb_1.Form.RecordSource = sql
Me.sb_1.Form.Requery
So the Filter should show an option where I can filter all the elements of the table and show it in the subform.
I just made an UNION that gives me all the data at once.
The SQL Select:
SELECT ID, Gerät FROM database_geräte UNION select "*" as ID, "Alle" as Gerät from database_geräte;
Then I made a function, that I can give to two Filters:
sql = "SELECT database_geräte.Gerät, database1.Name, database1.Grund, database1.Gerät_ID" _
& " FROM database_geräte INNER JOIN database1 ON database_geräte.ID = database1.Gerät_ID " _
& "" & IIf(Me.GeräteFilter <> "*", "Where database1.Gerät_ID = " & Me.GeräteFilter & " ", "") & " " _
& "" & IIf(Me.Person <> "Alle", IIf(Me.GeräteFilter <> "*", " AND database1.Name = '" & Me.Person & "'", "WHERE database1.Name = '" & Me.Person & "'"), "") & ""
Me.sb_1.Form.RecordSource = sql
Me.sb_1.Form.Requery

How to build dropdown list with database?

I have try to build dropdown list that bind with database. I found out some errors that i dont really found. Please help, here below is my codes.
strSQL = "SELECT distinct table1.DeptName FROM Table1 " & _
"FULL JOIN Table2 on table1.DeptName = Table2.deptname" & _
"FULL JOIN Table3 on Table1.deptname = table3.DeptName " & _
"Where table1.deptname is not null order by table1.deptname "
Common.OpenConn()
Common.execReader(strSQL, params, dt, Common.txn)
If dt.Rows.Count > 0 Then
DropDownListDept.DataSource = dt
DropDownListDept.DataTextField = "DeptName"
DropDownListDept.DataValueField = "DeptName"
DropDownListDept.DataBind()
DropDownListDept.Items.Insert(0, New ListItem("Select Department Name", "0"))
End If
error found
Invalid column name 'DeptNameFULL'.
Your error is in your sql statement... The database is looking for a field called "DeptNameFULL" and of course there isn't.
strSQL = "SELECT distinct table1.DeptName FROM Table1 " & _
"FULL JOIN Table2 on table1.DeptName = Table2.deptname" & _
"FULL JOIN Table3 on Table1.deptname = table3.DeptName " & _
"Where table1.deptname is not null order by table1.deptname "
On the second line - you need a space after "Table2.deptname" - so it should be Table2.deptname " instead.

(Ms Access) Row_Number() Over Partition

How can I convert the row_number() function with an over partition on MS ACCESS? What I want to achieve is:
from this table:
ID | EntryDate
10 | 2016-10-10
10 | 2016-12-10
10 | 2016-12-31
10 | 2017-01-31
10 | 2017-03-31
11 | 2015-01-31
11 | 2017-01-31
To this output, showing only the top 3 latest of each ID:
ID | EntryDate
10 | 2016-12-31
10 | 2017-01-31
10 | 2017-03-31
11 | 2015-01-31
11 | 2017-01-31
On SQL Server, i can achieved this using the following code:
select T.[ID],
T.[AptEndDate],
from (
select T.[ID],
T.[AptEndDate],
row_number() over(partition by T.[ID] order by T.[AptEndDate] desc) as rn
from Table1 as T
) as T
where T.rn <= 3;
Consider a count correlated subquery which can work in any RDBMS.
select T.[ID], T.[EntryDate]
from
(select sub.[ID],
sub.[EntryDate],
(select count(*) from Table1 c
where c.ID = sub.ID
and c.[EntryDate] >= sub.[EntryDate]) as rn
from Table1 as sub
) as T
where T.rn <= 3;
It might be simpler and faster to use Top n - as you mention yourself:
Select T.[ID], T.[EntryDate]
From Table1 As T
Where T.[EntryDate] In
(Select Top 3 S.[EntryDate]
From Table1 As S
Where S.[ID] = T.[ID]
Order By S.[EntryDate] Desc)
Order By T.[ID] Asc, T.[EntryDate] Asc
Anything using the OVER clause is something known as a Windowing Function. Unfortunately, MS Access does not have support for Windowing Functions.The easiest solution in this case may be to back to VBA code :(
Public Const tableName As String = "[TransactionalData$]"
Public Const parentId As String = "parentId"
Public Const elementId As String = "Id"
Public Const informationalField As String = "Label"
Sub TransactionalQuery(Optional ByVal Id As Integer = 0)
Dim rs As New ADODB.Recordset, cn As New ADODB.Connection
Dim sqlString As String
''' setup the connection to the current Worksheet --- this can be changed as needed for a different data source, this example is for EXCEL Worksheet
cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties='Excel 12.0 Macro;HDR=YES;IMEX=1'")
'''' Alternate method for the query
sqlString = "SELECT ParentId, Rank() OVER(PARTITION BY ParentId ORDER BY Label) , vlu.Id, vlu.Label FROM [TransactionalData$] var LEFT JOIN [TransactionalData$] vlu ON vlu.Id=var.ParentId"
''' will need to change the TableName (TransactionalData$]
sqlString = "SELECT DISTINCT " & elementId & " FROM " & tableName & " WHERE " & parentId & " = " & Id
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
'' Start collecting the SQL UNIONs to run at the end
sqlString = ""
Do While Not rs.EOF
'' Add current Element to the UNION
sqlString = sqlString & "SELECT * FROM " & tableName & " WHERE " & elementId & " = " & rs.Fields(elementId) & " UNION " & vbCrLf
'' Add all children element to the UNION
sqlString = sqlString & subQuery(cn, rs.Fields(elementId))
rs.MoveNext
Loop
rs.Close
'''Debug.Print sqlString
''' Remove the extra UNION keyword at the end
sqlString = Left(sqlString, Len(sqlString) - 8)
''' Exectue the built query
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
''Do While Not rs.EOF
'' Debug.Print rs.Fields(elementId) & ", " & rs.Fields(informationalField)
'' rs.MoveNext
''Loop
End Sub
Function subQuery(cn As ADODB.Connection, Id As Integer) As String
Dim sqlString As String
Dim subSqlString As String, rs As New ADODB.Recordset
'' Create a list of children for the current element
sqlString = "SELECT DISTINCT " & elementId & " FROM " & tableName & " WHERE " & parentId & " = " & Id
rs.Open sqlString, cn, adOpenStatic, adLockReadOnly
'' start the SQL for current elements children
sqlString = ""
Do While Not rs.EOF
''' add in the current element to the UNION
sqlString = sqlString & "SELECT * FROM " & tableName & " WHERE Id = " & rs.Fields(elementId) & " UNION " & vbCrLf
''' recursively find additional children for the current element
sqlString = sqlString & subQuery(cn, rs.Fields(elementId))
rs.MoveNext
Loop
rs.Close
''' return the SQL for the current element and all its children
subQuery = sqlString
End Function

syntax error in string in query in VBA access

I get 3075 error running this line in vba access:
Dim sqlMZG As String
sqlMZG = "SELECT MAZeitenGesamt.* Where MAZeitenGesamt.MA = 'JPA' FROM MAZeitenGesamt;"
Where JPA is a constant value. I tried the following forms and none of them worked.
SELECT MAZeitenGesamt.* Where MAZeitenGesamt.[MA] = '" & "JPA" & "' FROM MAZeitenGesamt;
SELECT MAZeitenGesamt.* Where MAZeitenGesamt.MA = '" & "JPA" & "' FROM MAZeitenGesamt;
SELECT MAZeitenGesamt.* Where MAZeitenGesamt.MA = ""JPA"" FROM MAZeitenGesamt;
SELECT MAZeitenGesamt.* Where MAZeitenGesamt.MA = \"JPA\" FROM MAZeitenGesamt;
SELECT MAZeitenGesamt.* Where MAZeitenGesamt.MA = \'JPA\' FROM MAZeitenGesamt;
Any ideas?
I'd recommend you use a parameter rather than quoting a literal. That said, #gizlmeier is right, in that your syntax is wrong to begin with.
Dim sqlMZG As String
sqlMZG = "parameters [MAParam] text; " & _
"SELECT MAZeitenGesamt.* FROM MAZeitenGesamt Where MAZeitenGesamt.MA = [MAParam];"
From there, when you create your query you can set the value for the parameter:
Set qry = CurrentDb.CreateQueryDef("GetMaz", sqlMZG)
qry.Parameters("MAParam") = JPA
No messy quoting to worry about and such.