SQL in VBA right join with no data from first table - sql

I try to join data from multiple workbooks and use it in current workbook instead of VLOOKUP function. So I do not want return key column, just those that match criteria in key column in current workbook.
I got "Syntax error in FROM clause."
Everything works fine without "RIGHT JOIN" part. I use ADO.
"SELECT t1.number " & _
"FROM" & _
"(SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src1.xlsm' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION ALL " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src2.xlsb' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;']" & _
"UNION ALL " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src2.xlsb' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;']) t1" & _
"RIGHT JOIN [Sheet1$] " & _
"IN '" & ThisWorkbook.FullName & "' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] t2 ON t2.key = t1.key;"
Data looks like
ThisWorkbook.Fullname:
key | someColumns | number
k1 | somedata |
k3 | somedata |
k5 | somedata |
\Src1.xlsm (also Src2):
key | number
k1 | 15
k2 | 11
k3 | 8
k4 | 16
k5 | 7
Likely result in Thisworkbook.fullname
key | someColumns | number
k1 | somedata | 15
k3 | somedata | 8
k5 | somedata | 7

Try
Dim Ws As Worksheet
Dim Rs As Object
Sub getRs(strSQL As String)
Dim strConn As String
Dim i As Integer
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties=Excel 12.0;"
Set Rs = CreateObject("ADODB.Recordset")
Rs.Open strSQL, strConn
End Sub
Sub test()
Dim strQuery As String
strQuery = "SELECT t1.number " & _
"FROM [Sheet1$] as t2 LEFT JOIN " & _
"(SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src1.xlsm' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION ALL " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Src2.xlsb' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;']) as t1 " & _
"ON t1.key = t2.key Where not isnull(t2.key) "
getRs strQuery
Range("c2").CopyFromRecordset Rs
Rs.Close
Set Rs = Nothing
End Sub

Related

Dynamically run strings in a loop

I want to run a string dynamically.
I'm trying to run a VBA loop to build a SQL Union for each record after the first. There could be anywhere from 1 record to 100. I want this to be dynamic so I don't have to limit the number of entries.
Example:
If I have 5 records it creates the SQL query with 4 unions. All the same data etc.
I'm trying to do is this:
When someone opens a form they will enter a list of pack numbers, from that they will select the range of offers under each pack number (All Offers, Promo, or Buyer).
The code then builds a union query for each pack number based on the the offer range they selected.
The output is all the data on those Offers under that pack number.
My full code: (I thought it necessary to get the full picture)
Private Sub ReviewButton_Click()
Dim Owner As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim qdfPassThrough As QueryDef
Dim strSeasonSQL As String
Dim strSeason As String
Dim strType As String
Owner = GetNamespace("MAPI").Session.CurrentUser.AddressEntry
If Me.NewRecord = True Then
Me!Owner.Value = Owner
End If
Set db = CurrentDb
Set rs = CurrentDb.OpenRecordset("RetailEntry")
'Set rs = CurrentDb.OpenRecordset("SELECT * FROM RetailEntry")
strSeason = [Forms]![Retail_Navigation]![NavigationSubform].[Form]![cboSeason]
strType = rs.Fields("Offer").Value '[Forms]![ReviewButton]![RetailEntry].[Form]![Offer].Value
On Error GoTo 1
1:
'Build Initial Query based on first record and make sure there are records
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'All Offers
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If rs.Fields("Offer") = "All Offers" Then
StrSQL = "Set NoCount ON DROP TABLE #catcov; " _
& "SELECT DISTINCT mailyear, offer, description, firstreleasemailed, season_id, offer_type, " _
& "case when description like '%Promo%' then 'Promo' " _
& "Else 'Buyer' end As addtype " _
& "INTO #catcov " _
strSELECT = "FROM supplychain_misc.dbo.catcov; " _
& "SELECT DISTINCT " _
& "a.PackNum " _
& ",a.Description " _
& ",a.CatID " _
& ",DATEPART(QUARTER, FirstReleaseMailed) as Quarter " _
& ",a.RetOne " _
& ",a.Ret2 " _
& ",a.ORIGINALRETAIL " _
& ",a.DiscountReasonCode " _
& ",b.Season_id " _
& ",a.year " _
& ",addtype "
strFROM = "FROM PIC704Current a JOIN #CatCov b ON (a.CatID = b.Offer) and (a.Year = b.MailYear) " _
strWHERE = "WHERE b.Offer_Type In('catalog', 'insert', 'kicker', 'statement insert', 'bangtail', 'onsert', 'outside ad') " _
& " and b.Season_id = '" & strSeason & "' " _
& " and (Case when b.FirstReleaseMailed >= cast(dateadd(day, +21, getdate()) as date) then 1 else 0 end) = 1 "
StrSQL = StrSQL & vbCrLf & strSELECT & vbCrLf & strFROM & vbCrLf & strWHERE
'Promo/Core
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ElseIf rs.Fields("Offer") = "Promo" Or rs.Fields("Offer") = "Buyer" Then
StrSQL = "Set NoCount ON DROP TABLE #catcov; " _
& "SELECT DISTINCT mailyear, offer, description, firstreleasemailed, season_id, offer_type, " _
& "case when description like '%Promo%' then 'Promo' " _
& "Else 'Buyer' end As addtype " _
& "INTO #catcov " _
strSELECT = "FROM supplychain_misc.dbo.catcov; " _
& "SELECT DISTINCT " _
& "a.PackNum " _
& ",a.Description " _
& ",a.CatID " _
& ",DATEPART(QUARTER, FirstReleaseMailed) as Quarter " _
& ",a.RetOne " _
& ",a.Ret2 " _
& ",a.ORIGINALRETAIL " _
& ",a.DiscountReasonCode " _
& ",b.Season_id " _
& ",a.year " _
& ",addtype "
strFROM = "FROM PIC704Current a JOIN #CatCov b ON (a.CatID = b.Offer) and (a.Year = b.MailYear) " _
strWHERE = "WHERE b.Offer_Type In('catalog', 'insert', 'kicker', 'statement insert', 'bangtail', 'onsert', 'outside ad') " _
& " and b.Season_id = '" & strSeason & "' and b.addtype = '" & strType & "' " _
& " and (Case when b.FirstReleaseMailed >= cast(dateadd(day, +21, getdate()) as date) then 1 else 0 end) = 1 "
StrSQL = StrSQL & vbCrLf & strSELECT & vbCrLf & strFROM & vbCrLf & strWHERE
End If
'Build/Loop Unions for each record after the first
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
rs.MoveNext
strType = rs.Fields("Offer").Value
Do Until rs.EOF = True
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'All Offers
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If rs.Fields("Offer") = "All Offers" Then
StrUnion = "UNION SELECT DISTINCT " _
& "a.PackNum " _
& ",a.Description " _
& ",a.CatID " _
& ",DATEPART(QUARTER, FirstReleaseMailed) as Quarter " _
& ",a.RetOne " _
& ",a.Ret2 " _
& ",a.ORIGINALRETAIL " _
& ",a.DiscountReasonCode " _
& ",b.Season_id " _
& ",a.year " _
& ",addtype "
strFROMnxt = "FROM PIC704Current a JOIN #CatCov b ON (a.CatID = b.Offer) and (a.Year = b.MailYear) " _
strWHEREnxt = "WHERE b.Offer_Type In('catalog', 'insert', 'kicker', 'statement insert', 'bangtail', 'onsert', 'outside ad') " _
& " and b.Season_id = '" & strSeason & "' " _
& " and (Case when b.FirstReleaseMailed >= cast(dateadd(day, +21, getdate()) as date) then 1 else 0 end) = 1 "
StrSQL2 = StrUnion & vbCrLf & strFROMnxt & vbCrLf & strWHEREnxt
'Promo/Buyer
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ElseIf rs.Fields("Offer") = "Promo" Or rs.Fields("Offer") = "Buyer" Then
StrUnion = "UNION SELECT DISTINCT " _
& "a.PackNum " _
& ",a.Description " _
& ",a.CatID " _
& ",DATEPART(QUARTER, FirstReleaseMailed) as Quarter " _
& ",a.RetOne " _
& ",a.Ret2 " _
& ",a.ORIGINALRETAIL " _
& ",a.DiscountReasonCode " _
& ",b.Season_id " _
& ",a.year " _
& ",addtype "
strFROMnxt = "FROM PIC704Current a JOIN #CatCov b ON (a.CatID = b.Offer) and (a.Year = b.MailYear) " _
strWHEREnxt = "WHERE b.Offer_Type In('catalog', 'insert', 'kicker', 'statement insert', 'bangtail', 'onsert', 'outside ad') " _
& " and b.Season_id = '" & strSeason & "' and b.addtype = '" & strType & "' " _
& " and (Case when b.FirstReleaseMailed >= cast(dateadd(day, +21, getdate()) as date) then 1 else 0 end) = 1 "
StrSQL2 = StrUnion & vbCrLf & strFROMnxt & vbCrLf & strWHEREnxt
End If
'Move to next Record and loop till EOF
rs.MoveNext
Loop
'If there are no Records then error
Else
MsgBox "There are no Pack Numbers Entered."
End If
'END QUERY
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Build Retail Bump File Pass Through Query
db.QueryDefs.Delete "qryMaster"
Set qdfPassThrough = db.CreateQueryDef("qryMaster")
qdfPassThrough.Connect = "ODBC;DSN=SupplyChainMisc;Description=SupplyChainMisc;Trusted_Connection=Yes;DATABASE=SupplyChain_Misc;"
qdfPassThrough.ReturnsRecords = True
qdfPassThrough.sql = StrSQL & vbCrLf & StrSQL2
rs.Close
Set rs = Nothing
DoCmd.OpenForm "SubCanButton"
DoCmd.OpenQuery "MasterQuery"
DoCmd.Close acForm, "ReviewButton"
End Sub
First, you do a "union distinct" when you don't include ALL:
UNION ALL
SELECT DISTINCT ...
Thus, as your selected records seem the same, only one will returned.
Second, including ALL or not, your concept doesn't make much sense. Why union a lot of identical records? Even if they hold different IDs only, they seem to be pulled from the same table, which you could with a single query.
Third, casting a date value to a date value does nothing good, so:
cast(dateadd(day, +21, getdate()) as date)
can be reduced to:
dateadd(day, +21, getdate())

Error executing a dynamic query with inner join (VBA) to dynamic tables

I'm sorry for my English ;)
I have consulted a lot on the internet but I cannot find the solution
I must create a dynamic query, with a function.
This code works for me if the tables are not linked, but are in the same bbdd ACCESS 2016.
But I need them to be in another bbdd.
Can you help me?
It returns me that data is missing.
The query is made in access and modified in vba, adding the variables.
Ano and Trimestre are numerical, the others are text.
Public Function PRUEBA_INNER(ByVal TRIMESTRE As String,ByVal ANO As String) As Boolean
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim StrSQL As String
Set db = CurrentDb
StrSQL = "SELECT " & _
"PERSONAS.NOMBRE, " & _
"PERSONAS.MAIL, " & _
"PERSONAS.[NUMR_COLEG], " & _
"DATOS_" & ANO & ".ANO, " & _
"DATOS_" & ANO & ".TRIMESTRE " & _
"FROM " & _
"PERSONAS " & _
"INNER JOIN DATOS_" & ANO & " " & _
"ON PERSONAS.[NUMR_COLEG] = DATOS_" & ANO & ".NUMR_COLEG " & _
"GROUP BY " & _
"PERSONAS.NOMBRE, " & _
"PERSONAS.MAIL, " & _
"PERSONAS.[NUMR_COLEG], " & _
"DATOS_" & ANO & ".ANO, " & _
"DATOS_" & ANO & ".TRIMESTRE " & _
"HAVING (((DATOS_" & ANO & ".ANO)=" & ANO & ")" & _
" AND ((DATOS_" & ANO & ".TRIMESTRE)=" & TRIMESTRE & "))"
Set rs = db.OpenRecordset(StrSQL)
Do Until rs.EOF
debug.print rs!nombre
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
db.Close: Set db = Nothing
End Function
Debug.print:
SELECT
PERSONAS.NOMBRE,
PERSONAS.MAIL,
PERSONAS.[NUMR_COLEG],
DATOS_2018.ANO,
DATOS_2018.TRIMESTRE
FROM
PERSONAS
INNER JOIN
DATOS_2018
ON
PERSONAS.[NUMR_COLEG] = DATOS_2018.NUMR_COLEG
GROUP BY
PERSONAS.NOMBRE,
PERSONAS.MAIL,
PERSONAS.[NUMR_COLEG],
DATOS_2018.ANO,
DATOS_2018.TRIMESTRE
HAVING (((DATOS_2018.ANO)=2018) AND ((DATOS_2018.TRIMESTRE)=2))
Error message:
nÂș 3061
Few parameters.
1 expected

Recordset Query - Excel

strQuery = _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source1.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source2.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$] " & _
"IN '" & ThisWorkbook.Path & "\Source3.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"ORDER BY A;"
Hi,
I have the above inside a Module in VBA (the code itself is sourced from here ). My question is, my columns in each file starts from row 15 and data goes down from row 16. How do I make it so that each file, it would look to UNION from row 15?
Thanks in advance!
With Excel workbook SQL queries via ADO or DAO, you can specify the regions of a worksheet by setting a range in the fashion: [Sheet$A1:Z2]. First find the last named column (recall for UNION they must be same lengths and types) and add rows sufficient for valid querying. Below uses Z999:
strQuery = _
"SELECT * FROM [Sheet1$A15:Z999] " & _
"IN '" & ThisWorkbook.Path & "\Source1.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$A15:Z999] " & _
"IN '" & ThisWorkbook.Path & "\Source2.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"UNION " & _
"SELECT * FROM [Sheet1$A15:Z999] " & _
"IN '" & ThisWorkbook.Path & "\Source3.xlsx' " & _
"[Excel 12.0;Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Extended Properties='HDR=YES;'] " & _
"ORDER BY A;"

How to create percentile function for a SQL query in MS Access that allows GROUP BY and filtering?

I'm attempting to write a domain function I can use in MS Access SQL view like what is found here: DMedian in access 2013, no values returned
...but for a DPercentile function that allows you to GROUP BY and filter.
This is what I have so far:
Public Function DPercentileWithGrpBy( _
ByVal sFld As String, _
ByVal sTable As String, _
ByVal iPercent As Integer, _
ByVal sGrpByFld As String, _
ByVal sGrpByValue As String _
) As Variant
Dim db As DAO.Database
Dim rstDomain As DAO.Recordset
Dim sSQL As String
Const errAppTypeError = 3169
On Error GoTo HandleErr
Set db = CurrentDb()
' Build SQL string for recordset.
sSQL = "SELECT " & _
sTable & "." & sGrpByFld & _
"," & (1 - iPercent / 100) & "*(" & _
"SELECT Max(" & sFld & ") " & _
"FROM " & sTable & " " & _
"WHERE " & sTable & "." & sFld & " IN (" & _
"SELECT TOP " & iPercent & " PERCENT " & sFld & " " & _
"FROM " & sTable & " " & _
"WHERE " & sTable & "." & sGrpByFld & " = " & Chr(34) & sGrpByValue & Chr(34) & " AND " & sFld & " Is Not Null ORDER BY " & sFld & ")) + " & iPercent / 100 & "*(" & _
"SELECT Min(" & sFld & ") " & _
"FROM " & sTable & " " & _
"WHERE " & sTable & "." & sFld & " IN (" & _
"SELECT TOP " & 100 - iPercent & " PERCENT " & sFld & " " & _
"FROM " & sTable & " " & _
"WHERE " & sTable & "." & sGrpByFld & " = " & Chr(34) & sGrpByValue & Chr(34) & " AND " & sFld & " Is Not Null ORDER BY " & sFld & " DESC)" & _
") AS " & iPercent & "Percentile " & _
"FROM " & sTable & " " & _
"WHERE " & sTable & "." & sGrpByFld & " = " & Chr(34) & sGrpByValue & Chr(34) & " " & _
"GROUP BY " & sTable & "." & sGrpByFld & ";"
'Debug.Print sSQL
'above should result in something like this:
'SELECT
' tblFirst250.[GICS Sector]
' , 0.75*(
' SELECT Max(GM)
' FROM tblFirst250
' WHERE tblFirst250.GM IN (
' SELECT TOP 25 PERCENT GM
' FROM tblFirst250
' WHERE tblFirst250.[GICS Sector] = "Energy" AND GM Is Not Null ORDER BY GM)) + 0.25*(
' SELECT Min(GM)
' FROM tblFirst250
' WHERE tblFirst250.GM IN (
' SELECT TOP 75 PERCENT GM
' FROM tblFirst250
' WHERE tblFirst250.[GICS Sector] = "Energy" AND GM Is Not Null ORDER BY GM DESC)
' ) AS 25Percentile
'FROM tblFirst250
'WHERE tblFirst250.[GICS Sector] = "Energy"
'GROUP BY tblFirst250.[GICS Sector];
Set rstDomain = db.OpenRecordset(sSQL, dbOpenDynaset)
DPercentileWithGrpBy = rstDomain
ExitHere:
On Error Resume Next
rstDomain.Close
Set rstDomain = Nothing
Exit Function
HandleErr:
' Return an error value.
DPercentileWithGrpBy = CVErr(Err.Number)
Resume ExitHere
End Function
I'd like to have the ability to use the function in MS Access SQL View as a query or part of a query. I also need to do a percentile (quartiles) of a sub group of records. Hopefully that make sense...
EDIT: the resulting query works when I debug.print it and using it in SQL View.
EDIT: here is how you could use it:
DPercentileWithGrpBy( "GM","tblFirst250", 25,"[GICS Sector]","Energy")

How do I delete files from a table in MSDE 2000 that is selected by 3 joins?

I have a VB6 program that uses a n Access backend. The query that I am currently using is
sQuery = "DELETE tblResultNotes.* " & _
"FROM (tblJobs INNER JOIN tblResults ON tblJobs.JobID=tblResults.JobID) INNER JOIN tblResultNotes ON tblResults.ResultID=tblResultNotes.ResultID " & _
"WHERE (tblJobs.CreateDate)< #" & strDate & "# " & _
"AND tblResults.StartTime < #" & strDate & "#;"
I have changed my backend to MSDE 2000 and now this query is giving me a syntax error near '*'. Could someone help me out?
Thanks,
Tom
Try changing your SQL to this:
sQuery = "DELETE FROM tblREsultNotes " & _
"FROM " & _
" tblJobs" & _
" INNER JOIN tblResults ON tblJobs.JobID=tblResults.JobID" & _
" INNER JOIN tblResultNotes ON tblResults.ResultID=tblResultNotes.ResultID" & _
"WHERE tblJobs.CreateDate < '" & strDate & "'" & _
"AND tblResults.StartTime < '" & strDate & "'"
Note the date delimiter change to ' instead of #.