select in select sql query - sql

I want to create a sql query. The column name that I want, it's in another table. I wrote this query.
SELECT (SELECT FieldName From TableGENQuest WHERE ID = 1)
FROM TableGEN
WHERE strSO = 'RV12648-01';
I want to get the data from the strGEN1 columns using the FieldName column of the TableGENQuest table.That is data I want No significant transportation damage observed.

tl;dr: Your request is not possible using MS Access SQL alone.
You will need to use VBA to open a recordset containing the content of the table TableGENQuest and construct an appropriate SQL statement whilst iterating over the records held by such recordset.
For example:
Sub GenerateQuery()
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim sql As String
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("SELECT FieldName FROM TableGENQuest WHERE ID = 1")
With rst
If Not .EOF Then
.MoveFirst
Do Until .EOF
sql = sql & "[" & !FieldName & "], "
.MoveNext
Loop
sql = "select " & Left(sql, Len(sql) - 2) & " from TableGEN WHERE strSO = 'RV12648-01';"
End If
.Close
End With
If sql <> vbNullString Then dbs.CreateQueryDef "OutputQuery", sql
Set rst = Nothing
Set dbs = Nothing
End Sub
The above will generate a query defined in the current database with a SQL statement selecting the fields whose fieldnames are sourced using the SQL:
SELECT FieldName FROM TableGENQuest WHERE ID = 1
The difficulty and convoluted nature of this method indicates that your database is poorly designed: the field names themselves should instead appear as rows within another table.

SELECT b.FieldName FROM TableGEN a
LEFT OUTER JOIN TableGENQuest b
ON a.ID=b.ID
WHERE a.strSO = 'RV12648-01'
AND b.ID=1
OR
SELECT a.strSO,b.FieldName,b.ID
FROM TableGEN a
LEFT OUTER JOIN
(
SELECT FieldName,ID From TableGENQuest WHERE ID = 1
)
b
ON a.ID = b.ID
WHERE strSO = 'RV12648-01'
Try This Query...or can change Join Type...

Try this:
SELECT TableGENQuest.FieldName
FROM TableGEN, TableGENQuest
WHERE TableGENQuest.ID=1 AND WHERE strSO = 'RV12648-01';

Related

VBA SQL returning null values

I'm having a problem running a SQL statement on vba excel, the last 3 Columns are for storing numbers separated by commas, but when executed on excel vba it doesn't display these values, while on other Database programs it does
the code is the following
Sub obtainColMachs()
Dim cnn1 As New ADODB.Connection
Dim mrs As New ADODB.Recordset, sqry As String
Set cnn1 = New ADODB.Connection
cnn1.ConnectionString = "driver=SQL Server Native Client 11.0;" & _
"server=server;uid=user;pwd=password;database=DB;"
cnn1.ConnectionTimeout = 3
cnn1.Open
sqry = "select top 1 m.* from recipe r left join RecipeGroup rg on r.RecipeGroupID = rg.RecipeGroupID " & _
"left join Matricula m on tonalidad_ID = ParentGroupID *100 + rg.RecipeGroupID where Substring(ColorNo,3,3) = 'ZG5'"
mrs.Open sqry, cnn1
Range("A26").CopyFromRecordset mrs
mrs.Close
cnn1.Close
End Sub
It should return:
But it only returns:
You only seem to be returning fields from your Matricula table; perhaps the SQL should be:
select top 1 m.*, r.*, rg.* from
Or better yet, a list of the fields that are actually required and with reference to the table from which they originate, e.g.:
select top 1 m.Tonalidad, m.Field2, r.Field3, rg.Field4 etc... from

Inserting a column from an SQL query into a data column in HPE UFT

This is the code in HPE UFT that successfully runs the query and displays a msg box.
I would like it to store the query results or at least 1 column of the query results in the HPE UFT data table so that I can run a loop on those loan numbers later.
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
objConnection.open "provider=123ABC;Server=T1;User Id=****;
Password=****; Database=i_prod;Trusted_Connection=Yes"
sqlQuery="SELECT Table1 AS LoanNumber, lm.loanrecordid, clm.istexasconversion as TexasConversion FROM Table1 lm WITH (NOLOCK) LEFT JOIN Table2 clm WITH (NOLOCK) ON clm.lenderdatabaseid = lm.lenderdatabaseid AND clm.loanrecordid = lm.loanrecordid Where clm.istexasconversion IS NOT NULL"
objRecordSet.open sqlQuery, objConnection
value = objRecordSet.fields.item(0)
msgbox Value
objRecordSet.Close
objConnection.Close
Set objConnection = Nothing
Set objRecordSet = Nothing
This is the query used in SQL.
SELECT
lm.loanid AS LoanNumber
,Column1
,column2 as Texas
FROM table1 lm WITH (NOLOCK)
LEFT JOIN table2 clm WITH (NOLOCK)
ON clm.lenderdatabaseid = lm.lenderdatabaseid
AND clm.loanrecordid = lm.loanrecordid
Desired Result Image
To start with, it helps if you define the parameter names initially in the table like this:
Datatable.AddParameter("LoanNumber", dtGlobal)
Datatable.AddParameter("LoanID", dtGlobal)
Datatable.AddParameter("TexasConversion", dtGlobal)
This will set the first three columns of the Global datatable with the name of the parameter you are going to insert.
Then, for ease of use, put the data in your RecordSet into an Array:
myArray = objRecordSet.GetRows ' do this before you close the recordset
And finally, loop around the two dimensional array to populate the table with data:
For myLoop = 0 to UBound(myArray, 2) ' loop over the total rows
DataTable.SetCurrentRow(myLoop + 1) ' +1 as row count starts from 1 not 0
Datatable("LoanNumber") = myArray(0, myLoop)
Datatable("LoanID") = myArray(1, myLoop)
Datatable("TexasConversion") = myArray(2, myLoop)
Next
And if you need to store a copy of the datatable (unless you plan to only use this data during the run, you will need to):
Datatable.Export("\\Path\To\File\To\Save.xlsx")
If you have any trouble following this, post a comment and I'll try to explain further.
You can use database output values to output the values from your column.
Steps to create database output values:
Select Insert> Output Values> Database Output Values
Create connection string
Choose in Query definition 'Specify SQL statement manually' radio button and maximum number of rows
In Sql statement edit field insert your query

Conditional inner join statement (VBA/SQL) to generate multiple values

I'm quite new to VBA/SQL and I'm trying to execute a conditional inner join.
I have two tables with a column in common ("CRM" and "CodeCRM") and I would like to obtain an email adress from table2 ("Desks") when something is triggered (CodeBlocage = 101) in table1 ("Flux") in order to add it to an automatic email.
Dim StrDestinataire As String
Select Case Strtable
Case "Flux", "GAFIJOUR"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim Y As String
Dim sSql As String
Set cn = CurrentProject.Connection
sSql = "Select AddMailCRM from Desks Inner Join Flux on Desks.CODECRM = Flux.CRM WHERE Flux.CODEBLOCAGE = '101'"
Set rs = cn.Execute(sSql)
If Not rs.BOF And Not rs.EOF Then
Y = rs.Fields("AddMailCRM").Value
End If
StrDestinataire = Y
cn.Close
Everything works great except that it should be returning more than one value for the email adress. Any leads?
Thank you
There are three keywords that may cause confusion:
SELECT in sql
SELECT determines the columns in the resulting recordset. If your sql statement is SELECT Name, Number FROM Employees, the SELECT part tells you that the resulting recordset will have two columns named Name and Number.
Select Case in VBA
Select Case is a programming construct for conditionals. You'd use it when you don't want to use a bunch of If..ElseIf..Else statements, but anything you can do with If you can do with Select Case.
Select Case A
Case "Flux"
Execute these VBA statements when the variable A = Flux
Case "Capacitor"
Execute these statements when A = Capacitor
Case Else
Execute these statements when A is neither Flux nor Capacitor
End Select
CASE in sql
The CASE keyword in sql is like Select Case in VBA, but it's used in the field list of a SELECT sql statement (for one).
SELECT Name, CASE WHEN Number = 1 THEN 'One' ELSE 'Two' END MyNum FROM Employees
If you execute this recordset, you get two columns (Name, MyNum). The MyNum field will contains the text One when Number is 1 for that record and the text Two if Number is anything but 1.
Recordsets
You have both Excel and Access tags, so I'm going to assume you're using ADO in either one of those. Your statement
Y = Select email from table2 Inner Join table1 on table2.Crm = table1.Crm WHERE table1.Code = 1
Doesn't do anything - it wouldn't compile. Let's assume you want a variable, Y, to contain the email that would be returned if you executed that sql statement.
Sub GetEmail()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim Y As String
Dim sSql As String
Set cn = New ADODB.Connection
cn.Open "MyConnectionStringGoesHere"
sSql = "Select email from table2 Inner Join table1 on table2.Crm = table1.Crm WHERE table1.Code = 1"
Set rs = cn.Execute(sSql)
If Not rs.BOF And Not rs.EOF Then
Y = rs.Fields("email").Value
End If
End Sub
In this case I have to create a recordset and execute that recordset for a certain connection. Presumably the join and the WHERE clause ensures that it will only return one record. But if it returns more, this example will only use the email from the first record.
Before I grab the Value of the email field, I make sure that the recordset returned at least one record. If it's at the beginning of the file (BOF) and at the end of the file (EOF) at the same time, that means there are no records in the recordset.
Solved.
Dim StrDestinataire As String
Select Case Strtable
Case "Flux", "GAFIJOUR"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim Y As String
Dim sSql As String
Set cn = CurrentProject.Connection
sSql = "Select AddMailCRM from Desks Inner Join Flux on Desks.CODECRM = Flux.CRM WHERE Flux.CODEBLOCAGE = '101'"
Set rs = cn.Execute(sSql)
If Not rs.BOF And Not rs.EOF Then
Y = rs.Fields("AddMailCRM").Value
End If
StrDestinataire = Y
cn.Close

VBA Iteration vs SQL Speed in Access

Goal: I have a bunch of dates, I want to update the records of the minimum date by category:
JVID APDATE TAG into > JVID APDATE TAG
1 201501 Use 1 201501 Don't Use
1 201502 Use 1 201502 Use
1 201502 Use 1 201502 Use
1 201503 Use 1 201503 Use
2 201502 Use 2 201502 Don't Use
2 201503 Use 2 201503 Use
The method I'm using is as follows:
I create a dictionary where the Key = ID, and Value = MinDateByID
Then I loop thorough the keys (for each key in dictionary) and run an update query for each ID that checks an IIF statement updating Use/Don't Use based on the date matching the min date.
This works, but w/ +80k IDs covering +1M records it takes forever.
I'm considering running the same thing, but dumping SQL and just iterating through the records, but I can't imagine that'd be faster?
I'm looking for SQL or VBA suggestions.
Thank you in advance!
EDIT - Added SQL From Comments
UPDATE [FY16 Q12 BE] SET [FY16 Q12 BE].[Record Use] = IIF([FY16 Q12 BE].[Date] = "201601", "Use", "Don't Use") WHERE ([FY16 Q12 BE].[ID]="20165645699");
I look through each of the dictionary key/value pairs ex (20165645699, 201601)
creating and running this script in various forms 80k+ times
MS Access is more restrictive than mainstream databases in joined updates, so I had to use a temporary table T2 to hold the minimum values.
SELECT T1.ID, MIN(T1.RDate) AS MinDate INTO T2
FROM Test1
GROUP BY T1.ID;
Now I can perform the joined update:
UPDATE T1 LEFT JOIN T2
ON T1.ID=T2.ID AND T1.RDate=T2.MinDate;
Finally, I drop the temporary table :
DROP T2;
SET TAG = IIF(T2.ID IS NULL, "Don't Use", "Use");
[I have named your table T1 and the date field RDate to avoid a conflict with a reserved word.]
This could be speeded up further by adding a primary key to T2 on (ID, MinDate) and an index on T1 on (ID, RDate).
I think you can do it with one update query - or at least a combination of multiple queries in one SQL statement.
I'm going to use your example data, since I can't figure out what your actual table or field names are in your comments.
You need to replace Table4 with your table name - and ID/Date/Tag fields to match your column names.
UPDATE SQL:
UPDATE Table4 SET Table4.Tag = "Don't Use"
WHERE ([Date] & "-" & [ID])
In (SELECT MergeID FROM
(SELECT Mins.[MinOfDate] & "-" & [ID] AS MergeID
FROM
(SELECT Table4.ID, Min(Table4.Date) AS MinOfDate
FROM Table4
WHERE Table4.Tag="Use"
GROUP BY Table4.ID) AS Mins) AS Merges);
If you don't need the criteria to only check TAGs that haven't been changed then you can eliminate the criteria WHERE Table4.Tag="Use"
OTHER 'No Tag Check' OPTION
UPDATE SQL:
UPDATE Table4 SET Table4.Tag = "Don't Use"
WHERE ([Date] & "-" & [ID])
In (SELECT MergeID FROM
(SELECT Mins.[MinOfDate] & "-" & [ID] AS MergeID
FROM
(SELECT Table4.ID, Min(Table4.Date) AS MinOfDate
FROM Table4
GROUP BY Table4.ID) AS Mins) AS Merges);
I want to suggest this. But I see you have duplicate dates and I'm not sure how you intend to handle these when you have ties for the earliest date.
update [FY16 Q12 BE]
set TAG = "Don't use"
where not exists (
select 1 from [FY16 Q12 BE] as t2
where t2.ID = [FY16 Q12 BE].ID and t2.[DATE] < [FY16 Q12 BE].[DATE]
)
I settled on an iterative approach - I'm not sure why it's so much faster than the SQL options outline above, but it does the trick. Thank you for your feedback.
Sub MinAPInclude(ByVal Tablename As String)
Dim db As DAO.Database
Dim qd As DAO.QueryDef
Dim rs As DAO.Recordset
Dim strList As String
Dim JVMinAP As Dictionary
Set JVMinAP = New Dictionary
Set db = DBEngine(0)(0)
Dim rst As DAO.Recordset
If Not DoesFieldExist(Tablename, "APDate") Then Exit Sub
SQLStatement = "SELECT [" & Tablename & "].[JVID], Min([" & Tablename & "].[APDate]) AS TargetAP"
SQLStatement = SQLStatement & " FROM [" & Tablename & "]"
SQLStatement = SQLStatement & " GROUP BY [" & Tablename & "].[JVID];"
Set qd = db.CreateQueryDef("", SQLStatement)
Set rs = qd.OpenRecordset
rs.MoveFirst
Do Until rs.EOF
If Not IsNull(rs("JVID")) Then
If Not JVMinAP.Exists(CStr(rs("JVID"))) Then
MinAP = rs("TargetAP")
JVMinAP.Add CStr(rs("JVID")), MinAP
End If
End If
rs.MoveNext
Loop
rs.Close
Set rst = db.OpenRecordset(Tablename)
rst.MoveFirst
Do Until rst.EOF
If rst("Record Use") <> "Include" Then
If rst("APDate") = JVMinAP(CStr(rst("JVID"))) Then
rst.Edit
rst("Record Use") = "Include"
rst.Update
End If
End If
rst.MoveNext
Loop
rst.Close
Set rst = nothing
Set rs = Nothing
Set qd = Nothing
Set db = Nothing
End Sub

Creating and using a table in the same transaction

I am trying to run a certain module in ms access. This is the part where I start running into problems:
For i= asc("A") To asc("C")
DBEngine.Workspaces(0).BeginTrans
'...a lot more code...
strSql = "SELECT table.string, Count(*) INTO tableCount FROM table LEFT JOIN table2 ON table.string= table2.string WHERE table2.string Is Null AND (((table.string) Like [param])) GROUP BY table.string HAVING (((Count(*))>1))"
DoCmd.SetWarnings False
Set qdf = CurrentDb.CreateQueryDef("", strSql)
qdf.Parameters("param").Value = Chr(i) & "*"
Call qdf.Execute(dbFailOnError)
DoCmd.SetWarnings True
If DCount("*", "tableCount") = 0 Then 'check if there were records
GoTo nextIteration
End If
'...a lot more code using tableCount if DCount shows that there are records...
DBEngine.Workspaces(0).CommitTrans
Next i
When arriving at the DCount check I get an error :
The Microsoft Access engine cannot find the input table or query 'tableCount'...
And the table doesn't appear in the db. I tried running the query that is in strSql in the Create Query in Access. When asked for param I enter A* and it works fine. The table tableCount is not created in the database before the transaction commit, But I need it inside the transaction, and not only for DCount. Is there a way to use the table or it's data before committing?
Please ask for any additional information you need in order to answer me, in comments. I will respond right away.
Use the following it is simpler and keeps everything within the transaction:
Dim dbS As DAO.Database
Dim wsP As DAO.Workspace
Dim lngRecs as Long
Set wsP = DBEngine.Workspaces(0)
Set dbS = CurrentDb
strSql = "SELECT table.string, Count(*) INTO tableCount FROM table LEFT JOIN table2 ON table.string= table2.string WHERE table2.string Is Null AND (((table.string) Like '" & Chr(i) & "*'")) GROUP BY table.string HAVING (((Count(*))>1))"
wsP.BeginTrans
dbS.Execute strSql, dbFailOnError
lngRecs = dbS.RecordsAffected
If Not lngRecs > 0 Then
GoTo nextIteration
End If
'Do whatever you like with lngRecs
wsP.CommitTrans dbForceOSFlush