SQL NOOB - nested/subqueires - sql

I will begin by clearly stating that I am not a programmer, I am an accountant at heart!
I have a need to return into excel all transactions relating to jobs that have had transactions in a given week (i.e. so that I can see an in week amount and total to date amount).
I'm reasonably proficient with VBA in excel (as accountants go anyway!) but I have always just copied and bodged the same old SQL statement. Essentially, what I think I need to do is a sub query in place of the order number of the WHERE statement in the following:
With Sheet1.QueryTables.Add(Connection:=Array(Array( _
"ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
.CommandText = Array( _
"SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, ", _
"SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" _
& Chr(13) & "" & Chr(10) & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" _
& Chr(13) & "" & Chr(10) & _
"WHERE (SLBGDTPF.ORDNO='30214884')")
.Name = "TEST Query"
.FieldNames = True
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False
End With
As a standalone query, what the sub-query element looks like is as follows:
With Sheet2.QueryTables.Add(Connection:=Array(Array( _
"ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
Array("512;QRYSTGLMT=-1;")), Destination:=Sheet2.Range("A1"))
.CommandText = Array( _
"SELECT SLBGDTPF.ORDNO" _
& Chr(13) & "" & Chr(10) & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" _
& Chr(13) & "" & Chr(10) & _
"WHERE SLBGDTPF.BGPSDT='20180420'" _
& Chr(13) & "" & Chr(10) & _
"GROUP BY SLBGDTPF.ORDNO")
.Name = "TEST Query"
.FieldNames = True
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False
End With
I'm open to all suggestions, including alternate approaches (I did try using IN and referencing a range in a sheet but I need to pass up to 1,000 different job numbers)
Just as an FYI, this is a template that will be sent out to people within the business to update themselves hence the need to build the connection, rather than just have them refresh an existing query(s) within the workbook.
All the best,
Joe

This can be achieved a few ways, but presuming the database can handle subqueries, I would try a WHERE IN term. I've also made some other cursory edits for clarity. The ultimate GROUP BY term is redundant in the subquery as there is only a single subquery SELECT field and no aggregation going on.
With Sheet1.QueryTables.Add(Connection:=Array(Array( _
"ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
.CommandText = Array( _
"SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
"WHERE SLBGDTPF.ORDNO IN (" & vbCrLf & _
"SELECT SLBGDTPF.ORDNO" & vbCrLf & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
"WHERE SLBGDTPF.BGPSDT='20180420')")
.Name = "TEST Query"
.FieldNames = True
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False
End With

As #IanPeters already mentioned, there are a few ways to handle this in SQL. I would like to add two versions that use a join instead of one of the WHERE clauses.
You might want to test which version performs best on your database. This will depend on the index structure on the database and on how well the query optimizer handles the query.
Subquery in join:
With Sheet1.QueryTables.Add(Connection:=Array(Array( _
"ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
.CommandText = Array( _
"SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
"INNER JOIN" & vbCrLf & _
"(SELECT S.ORDNO" & vbCrLf & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF S" & vbCrLf & _
"WHERE WeekOrders.BGPSDT='20180420') WeekOrders" & vbCrLf & _
"ON SLBGDTPF.ORDNO = WeekOrders.ORDNO")
.Name = "TEST Query"
.FieldNames = True
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False
End With
Condition outside of join:
With Sheet1.QueryTables.Add(Connection:=Array(Array( _
"ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
.CommandText = Array( _
"SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
"FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
"INNER JOIN RCHASE5C.LIVDTALIB.SLBGDTPF WeekOrders" & vbCrLf & _
"ON SLBGDTPF.ORDNO = WeekOrders.ORDNO" & vbCrLf & _
"WHERE WeekOrders.BGPSDT='20180420'")
.Name = "TEST Query"
.FieldNames = True
.RefreshStyle = xlOverwriteCells
.Refresh BackgroundQuery:=False
End With

Related

operation not allowed when object is closed "SQL connection giving error with VBA"

I am facing an issue while running a long SQL query with VBA, but when I run a simple one-line select query it works fine BUT
when I run the below complex query it fails, also I'd like to input some values from a defined range/cell into sql query like I would like to input L1100 as timezone from cell A2, what format should i use, any suggestions on this would be much appreciated
Public DBConn As ADODB.Connection
Public Sub createconn()
Dim UserId, Password As String
Set DBConn = New ADODB.Connection
Server = "XXXX"
UserId = "XXXXX"
Password = "XXXX"
With DBConn
.CommandTimeout = 30
.Open "PROVIDER=MSDASQL;" & _
"DRIVER={Microsoft ODBC for Oracle};" & _
"SERVER=" & Server & ";" & _
"UID=" & UserId & ";PWD=" & Password & ";"
End With
End Sub
Sub Stalecheck()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim DBresults As ADODB.Recordset
Dim sqlquery As String, wsData As Worksheet, Datasht As Worksheet
Dim elr As Long
Dim lRow As Long
Set DBresults = New ADODB.Recordset
Set wsData = Worksheets("Sheet1")
Set Datasht = ThisWorkbook.Sheets("Data")
'wsData.Range("U5:Y5", Range("U5").End(xlDown)).Clear
Datasht.Cells.ClearContents
'lRow = wsData.Cells(Rows.Count, 14).End(xlUp).Row
'Worksheets("UPDATER").Range("N2", "N" & lRow).Copy Destination:=Worksheets("UPDATER").Range("V5")
'Mainsheet.Range("B7:B15").ClearContents
If wsData.Range("B3").Value <> "" Then
Call createconn
'sqlquery = "select * from instrument_equity"
sqlquery = "select i.name, i.pkey, nvl(i.enddate,round((i.periodyears * 365.25),0) + vyc.asof) maturity," & vbNewLine & _
"nvl(i.period,i.enddate) period, vyc.asof, vyc.timezone, vyc.snaptime, vyc.rowkey, nvl(nvl(pfx.price, p.rate*100),vp.rate) rate," & vbNewLine & _
"nvl(nvl(pfx.updatetime, p.snaptime),vp.updatetime) updatetime, vms.symbol source" & vbNewLine & _
"from val_yield_curves vyc" & vbNewLine & _
"JOIN val_yc_def_elements el ON el.pkey=valuations_yieldcurves.getCurveDefinitionKey(vyc.asof, vyc.object_id)" & vbNewLine & _
"JOIN instruments i on i.pkey = el.instrument" & vbNewLine & _
"LEFT JOIN (SELECT asof, curve, instrument, rate*100 rate, quality, source, updatetime, bid, ask FROM val_prices_interestrates" & vbNewLine & _
"UNION SELECT asof, curve, instrument, rate*100, quality, source, updatetime, bid, ask FROM val_prices_basisswaps" & vbNewLine & _
"UNION SELECT asof, curve, instrument, rate*100, quality, source, updatetime, bid, ask FROM val_prices_oisrates" & vbNewLine & _
"UNION SELECT asof, curve, instrument, rate, quality, source, updatetime, bid, ask FROM val_prices_fx)" & vbNewLine & _
"vp ON i.pkey = vp.instrument" & vbNewLine & _
"and vp.asof=vyc.asof" & vbNewLine & _
"and vp.curve=vyc.rowkey" & vbNewLine & _
"LEFT JOIN prices_fixings p ON p.instrument = i.pkey and p.asof = vyc.asof" & vbNewLine & _
"LEFT JOIN val_prices_fxfixings pfx ON pfx.instrument = i.pkey" & vbNewLine & _
"and pfx.asof = vyc.asof" & vbNewLine & _
"and pfx.timezone = vyc.timezone" & vbNewLine & _
"LEFT JOIN val_mds_sources vms ON vms.pkey = vp.source" & vbNewLine & _
"WHERE vyc.asof = '11Jul20'" & vbNewLine & _
"and vyc.timezone = 'L1000'" & vbNewLine & _
"and vyc.object_id like 'CAD_IRIndex_3M'" & vbNewLine & _
"and i.type <> 'Future'" & vbNewLine & _
"ORDER BY vyc.object_id, i.type desc, el.type, i.ccy, i.ccy2, nvl(i.periodyears, nvl((i.enddate-trunc(sysdate))/365,0)), vyc.snaptime DESC"
'sqlquery = Left(sqlquery, Len(sqlquery) - 1) & ")"
DBresults.Open sqlquery, DBConn, adOpenDynamic
If Not DBresults.EOF Then Datasht.Range("A1").CopyFromRecordset DBresults
End If
Set DBresults = Nothing
Call close_conn
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Sub close_conn()
DBConn.Close
End Sub

Query with conditions based on cells

I am trying to write a VBA code that Queries some values.
My SQL query has two conditions in the WHERE statement.
The value in column B is within the query, so no issue about it.
The value in column A is a code which starts with numbers, but contains Letters and should be seen as a string as such to work '6F3S'; specifically: database.columnA='6F3S'.
My issue comes from the fact that I want to outsource the element 6F3S in cell D1 in sheet "Input_sheet", so that the user can change it with other codes if necessary.
This is my code so far:
Sub Query1()
Dim ValueCellD1 As String
ValueCellD1 = Worksheets("Input_Sheet").Range("D1").Value
With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
"FFFF;DSN=XXXXXXXXXXXX;", Destination:=Range("$A$7")).QueryTable
.CommandText = Array( _
"SELECT database.columnA, database.columnB, database.columnC" _
& Chr(13) & "" & Chr(10) & _
"FROM IMPALA.database database" _
& Chr(13) & "" & Chr(10) & _
"WHERE (database.columnA=ValueCellD1) AND (database.columnB='London')")
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = True
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.ListObject.DisplayName = "YYYYYYYYYYYYYYYYY"
.Refresh BackgroundQuery:=False
End With
End Sub
I receive a
Run-time error '13': Type mismatch
When I try to debug it appears being here:
.CommandText = Array( _
"SELECT database.columnA, database.columnB, database.columnC" _
& Chr(13) & "" & Chr(10) & _
"FROM IMPALA.database database" _
& Chr(13) & "" & Chr(10) & _
"WHERE (database.columnA=ValueCellD1) AND (database.columnB='London')")
Note: I am currently using Excel 2010
You need to get ValueCellD1 out of the string so it is recognized as variable.
.CommandText = Array( _
"SELECT database.columnA, database.columnB, database.columnC" _
& Chr(13) & "" & Chr(10) & _
"FROM IMPALA.database database" _
& Chr(13) & "" & Chr(10) & _
"WHERE (database.columnA='" & ValueCellD1 & "') AND (database.columnB='London')")
Actually I have no idea why you insert & Chr(13) & "" & Chr(10) & in your string. The following should work too:
.CommandText = Array( _
"SELECT database.columnA, database.columnB, database.columnC " _
"FROM IMPALA.database database " _
"WHERE (database.columnA='" & ValueCellD1 & "') AND (database.columnB='London')")
Note that if you read a cell value into your variable
ValueCellD1 = Worksheets("Input_Sheet").Range("D1").Value
and push this into your SQL command without verifying the cell value, then anyone who can edit the cell value in D1 can easily attack your database and run any SQL command he likes (eg delete it). Never trust user input. Always validate it.
See https://en.wikipedia.org/wiki/SQL_injection.

Runtime error '1004' General odbc error while refreshing excel sheet to get updated data

We are using shared folder in server where we keep all excel sheets based on our business requirement so whoever requires that document he will picked up that document from that shared folder and he will receive all update/manipulated data by clicking on "Refresh" button in "Data" tab in excel 2007,so in my organization everybody pc is working fine and they are getting updated data by refreshing document but in my pc the movement i click on refresh i am getting this error which is in image below please provide me a clear answer.
Sub TT_Out()
' ' Macro2 Macro
Dim RngFromDate, RngToDate
RngFromDate = InputBox("Enter Start Date !", "TT Out", Date - 1)
RngToDate = InputBox("Enter End Date !", "TT Out", RngFromDate)
With Range("Table_Query_from_ALXORCL[TT_OUT_DATE]").ListObject.QueryTable
.Connection = Array(Array( _
"ODBC;DRIVER={Oracle in instantclient_12_1};" & _
"SERVER=ALXORCL;UID=ALXLIVE;PWD=alx123;" & _
"DBQ=ALXORCL;DBA=W;APA=T;EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;F"), _
Array("DL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;" & _
"DPM=F;MTS=T;MDI=Me;CSR=F;FWC=F;FBS=60000;TLO=O;" & _
"MLD=0;ODA=F;STE=F;TSZ=8"), Array("192;"))
.CommandText = Array( _
" SELECT ALX_TT_OUT.TT_OUT_CODE, " & _
" ALX_TT_OUT.TT_OUT_DATE, " & _
" ALX_TT_OUT.F_NAME, " & _
" ALX_TT_OUT.B_F_NAME, " & _
" ALX_TT_OUT.SENDING_PRPS, " & _
" ALX_LOOKUP_DET.LOOKUP_DET_NAME||'-'||ALX_TT_OUT.DOC_NO, " & _
" ALX_PRODUCT.PRODUCT_CODE, " & _
" ALX_TT_OUT.QTY*ALX_TT_OUT.SELL_RATE, " & _
" ALX_CORRESPONDENT.CORRESPONDENT_NAME" & Chr(13) & Chr(10) & _
" FROM ALXTEST.ALX_CORRESPONDENT ALX_CORRESPONDENT, ALXTEST2.ALX_LOOKUP_DET ALX_LOOKUP_DET, ALXTEST2.ALX_PRODUCT ALX_PRODUCT, ALXL", _
" IVE.ALX_TT_OUT ALX_TT_OUT" & Chr(13) & "" & Chr(10) & _
" WHERE ALX_PRODUCT.PRODUCT_ID = ALX_TT_OUT.PRODUCT_ID " & _
" AND ALX_TT_OUT.CORRESPONDENT_ID = ALX_CORRESPONDENT.CORRESPONDENT_ID " & _
" AND ALX_LOOKUP_DET.LOOKUP_DET_ID = ALX_TT_OUT.DOC_TYPE_L ", _
" AND ((ALX_TT_OUT.TT_OUT_CODE Not Like '%HOF%') " & _
" AND (to_date(TT_OUT_DATE) Between '" & RngFromDate & "' And '" & RngToDate & "') " & _
" )")
.Refresh BackgroundQuery:=False
End With
End Sub

How to insert into a TEMP Table in VBA

When I run the following code I receive an error, "Run-time error '1004': Application-defined or object-defined error"
When I select debug, the following line is highlighted: .Refresh BackgroundQuery:=False
querystr = "SET NOCOUNT ON" & Chr(13) & _
"SELECT CSD.StoreNo AS 'StoreNo',SUM(CSD.Amount) as totalSales " & Chr(13) & _
"INTO #SalesOfTheStores " & Chr(13) & _
"FROM Purchase.dbo.CashsheetDetail as CSD " & Chr(13) & _
"INNER JOIN Purchase.dbo.CashsheetHeader as CSH on CSH.TransferID = CSD.TransferID and CSH.StoreNo = CSD.StoreNo " & Chr(13) & _
"WHERE CSD.Comments = 'Total Gross Sales' AND CSH.DayendDate between '" & StartDate & "' And '" & EndDate & "' " & Chr(13) & _
"GROUP BY CSD.StoreNo; "
With ActiveSheet.QueryTables.Add(Connection:= _
"ODBC;DRIVER=SQL Server;SERVER=" & Div & "DBL01\SR;UID=" & User & ";APP=Microsoft Office 2003;WSID=" & PC & ";DATABASE=Purchase;Trusted_Connection=Yes" _
, Destination:=Range("A1"))
.RefreshStyle = xlOverwriteCells
.CommandText = querystr
.Refresh BackgroundQuery:=False
End With
Your query string does not return data. Change your SQL to be a SELECT statement rather than a SELECT INTO (remove the INTO clause).

Error adding code to workbook via VBA

I am trying to use VBA in Excel to add conditional formatting to a column of a pivot table. The issue is that whenever the pivot table is refreshed, or a filter is changed, etc. the conditional formatting is lost. My solution was to add a macro to the pivot table update event in the workbook, which works ... kinda. It seems that when I run the code that creates the pivot table and adds the code to handle conditional formatting an error occurs but ONLY when the VBA window is NOT open. If the VBA window is open the code executes normally - despite no code changes or reference changes.
Private Sub setupConditionalFormattingForStatusColumn()
Dim thisSheetModule As vbcomponent
Dim formattingCodeString As String
On Error GoTo conditionalFormattingError
formattingCodeString = _
"Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)" & vbNewLine & _
" With Target.parent.Columns(" & harReportColumn("Status") & ")" & vbNewLine & _
" .FormatConditions.AddIconSetCondition" & vbNewLine & _
" .FormatConditions(.FormatConditions.Count).SetFirstPriority" & vbNewLine & _
vbNewLine & _
" With .FormatConditions(1)" & vbNewLine & _
" .IconSet = ActiveWorkbook.IconSets(xl4TrafficLights)" & vbNewLine & _
" .IconCriteria(1).Icon = xlIconYellowExclamation" & vbNewLine & _
vbNewLine & _
" With .IconCriteria(2) " & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = -1" & vbNewLine & _
" .Operator = 5" & vbNewLine & _
" .Icon = xlIconGreenCircle" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" With .IconCriteria(3)" & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = 1.05" & vbNewLine & _
" .Operator = 7" & vbNewLine & _
" .Icon = xlIconYellowCircle" & vbNewLine & _
" End With" & vbNewLine
formattingCodeString = formattingCodeString & vbNewLine & _
" With .IconCriteria(4)" & vbNewLine & _
" .Type = xlConditionValueNumber" & vbNewLine & _
" .value = 1.15" & vbNewLine & _
" .Operator = 7" & vbNewLine & _
" .Icon = xlIconRedCircleWithBorder" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" .ShowIconOnly = True" & vbNewLine & _
" End With" & vbNewLine & _
vbNewLine & _
" .HorizontalAlignment = xlCenter" & vbNewLine & _
" .VerticalAlignment = xlCenter" & vbNewLine & _
" End With" & vbNewLine & _
"End Sub"
Set thisSheetModule = ThisWorkbook.VBProject.VBComponents(harReportSheet.CodeName)
thisSheetModule.CodeModule.AddFromString formattingCodeString
Exit Sub
conditionalFormattingError:
errorLog.logError "WARNING: An error occured while applying the conditional formatting code for the ""Status"" column."
Err.Clear
Resume Next
End Sub
The line which generates the error is: thisSheetModule.CodeModule.AddFromString formattingCodeString but the error is only generated if the VBA window is closed.
Any ideas?
So I was able to find an answer to this issue. Evidently Excel does not properly initialize the codename property of newly created worksheets when the VBA window is not open (the why here is beyond me) but only when it recompiles. A work-around is to force Excel to recompile prior to any calls to the codename property. The solution which worked for me was to place the following code:
On Error Resume Next
Application.VBE.CommandBars.ActiveMenuBar.FindControl(ID:=578).Execute
On Error GoTo conditionalFormattingError
above the line beginning with Set thisSheetModule = ... . Oddly enough the line of code which forces the recompile also throws an error for me which I was able to safely ignore with the surrounding error handling.
More information can be found here: http://www.office-archive.com/2-excel/d334bf65aeafc392.htm
Hope that helps someone out there. :-)