Displaying "Similar" or "Related" Vehicles - sql

I have a vehicle database and would like to show "related" vehicles when a user clicks to view a vehicle. For instance, the user views a '2013 Chevy Tahoe' that is listed by dealership 'ABC Dealers'.
I need to create a SQL statement to grab 4 vehicles that are similar to the vehicle they are viewing. Here is the order of importance for now:
1) Dealer Listings (d_id)(Show vehicles also listed by that dealer)
2) Vehicle Category (vc_id)(Vehicle category such as Car, Truck, SUV, etc.)
3) Vehicle Make (vm_id)(Vehicle make such as Ford, Chevy, Lexus, etc.)
I have created a SQL statement, but it does not seem to do what I am looking for it to do. Can anyone offer any suggestions on how to properly build a SQL statement to grab the most relevant records in the order defined above?
strSQL = "SELECT TOP 4 v.v_id, vm.vm_name, v.v_year, v.v_model, v.v_search_price, d.d_name, u.u_name " & _
"FROM tbl_Vehicles v " & _
"LEFT JOIN tbl_VehicleMake vm ON vm.vm_id = v.vm_id " & _
"LEFT JOIN tbl_Dealers d ON d.d_id = v.d_id " & _
"LEFT JOIN tbl_Users u ON u.u_id = v.u_id " & _
"WHERE v.v_processed = 1 AND v.v_active = 1 AND v.v_id <> " & v_id
If Not CheckBlank(d_id) Then
strSQL = strSQL & " OR v.d_id = " & d_id
End If
If Not CheckBlank(vm_id) Then
strSQL = strSQL & " OR v.vm_id = " & vm_id
End If
If Not CheckBlank(vc_id) Then
strSQL = strSQL & " OR v.vc_id = " & vc_id
End If
strSQL = strSQL & " ORDER BY v.d_id, v.vc_id, v.vm_id"

I have a couple of thoughts for you.
Your current query has some ANDs and some ORs. You may need brackets to indicate your preferred order of operations, for example:
strSQL = "SELECT TOP 4 v.v_id, vm.vm_name, v.v_year, v.v_model, v.v_search_price, d.d_name, u.u_name " & _
"FROM tbl_Vehicles v " & _
"LEFT JOIN tbl_VehicleMake vm ON vm.vm_id = v.vm_id " & _
"LEFT JOIN tbl_Dealers d ON d.d_id = v.d_id " & _
"LEFT JOIN tbl_Users u ON u.u_id = v.u_id " & _
"WHERE v.v_processed = 1 AND v.v_active = 1 AND v.v_id <> " & v_id
If Not CheckBlank(d_id) Or Not CheckBlank(vm_id) Or Not CheckBlank(vc_id) Then
strSQL = strSQL & "("
End If
If Not CheckBlank(d_id) Then
strSQL = strSQL & " OR v.d_id = " & d_id
End If
If Not CheckBlank(vm_id) Then
strSQL = strSQL & " OR v.vm_id = " & vm_id
End If
If Not CheckBlank(vc_id) Then
strSQL = strSQL & " OR v.vc_id = " & vc_id
End If
If Not CheckBlank(d_id) Or Not CheckBlank(vm_id) Or Not CheckBlank(vc_id) Then
strSQL = strSQL & ")"
End If
strSQL = strSQL & " ORDER BY v.d_id, v.vc_id, v.vm_id"
But based on what you wrote in your question, you may be better with a query that uses the ORDER BY clause to get the most appropriate records based on the criteria you specified.
strSQL = "SELECT TOP 4 v.v_id, vm.vm_name, v.v_year, v.v_model, v.v_search_price, d.d_name, u.u_name " & _
"FROM tbl_Vehicles v " & _
"LEFT JOIN tbl_VehicleMake vm ON vm.vm_id = v.vm_id " & _
"LEFT JOIN tbl_Dealers d ON d.d_id = v.d_id " & _
"LEFT JOIN tbl_Users u ON u.u_id = v.u_id " & _
"WHERE v.v_processed = 1 AND v.v_active = 1 AND v.v_id <> " & v_id & " ORDER BY"
If Not CheckBlank(d_id) Or Not CheckBlank(vm_id) Or Not CheckBlank(vc_id) Then
If Not CheckBlank(d_id) Then
strSQL = strSQL & " CASE WHEN v.d_id = " & d_id & " THEN 0 ELSE 1 END,"
End If
If Not CheckBlank(vm_id) Then
strSQL = strSQL & " CASE WHEN v.vm_id = " & vm_id & " THEN 0 ELSE 1 END,"
End If
If Not CheckBlank(vc_id) Then
strSQL = strSQL & " CASE WHEN v.vc_id = " & vc_id & " THEN 0 ELSE 1 END,"
End If
strSQL = Left(strSQL, Len(strSQL) - 1)
Else
strSQL = strSQL & "v.d_id, v.vc_id, v.vm_id"
End If
This query will still give you results even if there are no vehicles for that dealer, make or category, so you will always have related vehicles (assuming you have at least 5 records).

It looks like the OR clauses you're using are not going to bring you you want. Assuming I'm understanding the snippet and the unseen db correctly, you need to create a subclause of the OR statements that is "ANDED" in. Try the following, after the initial strSQL assignment:
...
dim strSubClause
strSubClause = ""
If Not CheckBlank(d_id)) Then
strSubClause = "v.d_id = " & d_id
End If
If Not CheckBlank(vm_id) Then
If len(strSubClause) > 0 then
strSubClause = strSubClause & " OR v.vm_id = " & vm_id
Else
strSubClause = "v.vm_id = " & vm_id
End If
End If
If Not CheckBlank(vc_id) Then
If len(strSubClause) > 0 then
strSubClause = strSubClause & " OR v.vc_id = " & vc_id
Else
strSubClause = "v.vc_id = " & vc_id
End if
End If
If len(strSubClause) > 0 then
strSQL = " AND (" & strSubClause & ")"
End If
strSQL = strSQL & " ORDER BY v.d_id, v.vc_id, v.vm_id"
So, assuming all of your checks came back with values, you'd have a where clause that looks like:
...WHERE v.v_processed = 1 AND v.v_active = 1 AND v.v_id <> NNN AND (v.d_id = XXX OR v.vm_id = YYY OR v.vc_id = ZZZ) ORDER BY v.d_id, v.vc_id, v.vm_id
Does that make sense and/or get you closer or all the way to where you're wanting to go?

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())

SQL/ACCESS Function Not Working As Intended

Public Function GetPendingChangeOrders(strJ As String) As Double
strSQL = "SELECT DISTINCT Sum(jcdetail.cost) AS SumOfcost " &
"FROM jcchangeorder INNER JOIN jcdetail ON (jcchangeorder.ordernum = jcdetail.ponum) AND (jcchangeorder.jobnum =jcdetail.jobnum) " &
"GROUP BY jcdetail.jobnum, jcdetail.type, jcchangeorder.type, IIf(DLookUp(""type"",""jcchangeorderstep"",""jobnum = '"" & [jcchangeorder].[jobnum] & ""' and ordernum = '"" & [ordernum] & ""' and Type = 20"")=20,-1,0) " & _
"HAVING (((jcdetail.jobnum)='" & strJ & "') AND ((jcdetail.type)=19) AND ((jcchangeorder.type)<>2) AND ((IIf(DLookUp(""type"",""jcchangeorderstep"",""jobnum = '"" & [jcchangeorder].[jobnum] & ""' and ordernum = '"" & [ordernum] & ""' and Type = 20"")=20,-1,0))=0));"
Set rs = dbs.OpenRecordset(strSQL, dbOpenSnapshot, dbReadOnly, dbReadOnly)
If Not rs.EOF Then
dblResult = Nz(rs.Fields(0), 0)
rs.Close
Set rs = Nothing
GetPendingChangeOrders = dblResult
Else
GetPendingChangeOrders = 0
End If
End Function
So I got tossed into some MS-Access database with VBA/SQL statements all over.
I am literally a beginner, but I have managed to figure some things out, and familiarize myself with our database that we use to print out job reports.
Some of the call functions are setup wrong, and are pulling from the wrong tables, and I basically need some help figuring out which way I should be going to tackle this.
Currently if we run the report, and it calls "GetPendingChangeOrders" it does what it is supposed to do, but when we look at what is under pending.
It shows a result even though it has a status of 21(DENIED) inside of "JCCHANGEORDERSTEP" table. I included images of it.
JCCHANGEORDER has the same as columns as JCCHANGEORDERSTEP(JOBNUM,ORDERNUM,TYPE) but the types in JCCHANGEORDER just has a type of 1 which I assume says hey I'm active.
JCCHANGEORDERSTEP contains 1 initiated (pending), 20 (approved), 21(denied). It filters out the 20's from results on report, but not 21. So I just need some help, and an explanation of why just adding 21 into the mix didn't work.
Thank you for your time.
EDIT-1 ADDED IMGS
IMGUR ACCESS PICTURES
Having looked at your images and studied your existing SQL code, I think the following SQL query may be more suitable and altogether more readable:
select sum(d.cost) as sumofcost
from
(
jcchangeorder o inner join jcdetail d
on o.ordernum = d.ponum and o.jobnum = d.jobnum
) inner join
(
select distinct s.jobnum, s.ordernum
from jcchangeorderstep s
where s.type = 1
) q
on o.jobnum = q.jobnum and o.ordernum = q.ordernum
where
o.jobnum = ?job and d.type = 19 and o.type <> 2
Here, the inclusion of jcdetail records for which the jcchangeorderstep.type = 1 is handled by the inner join between the tables, rather than a separate dlookup for every record.
You could implement this in your function in the following way:
Public Function GetPendingChangeOrders(strJ As String) As Double
Dim strS As String
strS = strS & "select sum(d.cost) "
strS = strS & "from "
strS = strS & " ( "
strS = strS & " jcchangeorder o inner join jcdetail d "
strS = strS & " on o.ordernum = d.ponum and o.jobnum = d.jobnum "
strS = strS & " ) inner join "
strS = strS & " ( "
strS = strS & " select distinct s.jobnum, s.ordernum "
strS = strS & " from jcchangeorderstep s "
strS = strS & " where s.type = 1 "
strS = strS & " ) q "
strS = strS & " on o.jobnum = q.jobnum and o.ordernum = q.ordernum "
strS = strS & "where "
strS = strS & " o.jobnum = ?job and d.type = 19 and o.type <> 2 "
Dim rst As DAO.Recordset
With CurrentDb.CreateQueryDef("", strS)
.Parameters(0) = strJ
Set rst = .OpenRecordset
If Not rst.EOF Then
rst.MoveFirst
GetPendingChangeOrders = Nz(rst.Fields(0), 0)
End If
rst.Close
End With
End Function
EDIT:
Following the subsequent comments, the following seems more aligned with your requirements:
select sum(d.cost)
from
jcchangeorder o inner join jcdetail d
on o.ordernum = d.ponum and o.jobnum = d.jobnum
where
o.jobnum = jobparam and
d.type = 19 and
o.type <> 2 and
not exists
(
select 1 from jcchangeorderstep s
where s.jobnum = o.jobnum and s.ordernum = o.ordernum and s.type <> 1
)
This may be implemented in your VBA function in the following way:
Public Function GetPendingChangeOrders(strJ As String) As Double
Dim strS As String
strS = strS & "select sum(d.cost) "
strS = strS & "from "
strS = strS & " jcchangeorder o inner join jcdetail d "
strS = strS & " on o.ordernum = d.ponum and o.jobnum = d.jobnum "
strS = strS & "where "
strS = strS & " o.jobnum = jobparam and "
strS = strS & " d.type = 19 and "
strS = strS & " o.type <> 2 and "
strS = strS & " not exists "
strS = strS & " ( "
strS = strS & " select 1 from jcchangeorderstep s "
strS = strS & " where s.jobnum = o.jobnum and s.ordernum = o.ordernum and s.type <> 1 "
strS = strS & " ) "
Dim rst As DAO.Recordset
With CurrentDb.CreateQueryDef("", strS)
.Parameters("jobparam") = strJ
Set rst = .OpenRecordset
If Not rst.EOF Then
rst.MoveFirst
GetPendingChangeOrders = Nz(rst.Fields(0), 0)
End If
rst.Close
End With
End Function
This part of the query in your HAVING and GROUP BY clauses is what's giving you problems:
IIf(DLookUp("type",
"jcchangeorderstep",
"jobnum = ' [jcchangeorder].[jobnum] ' and
ordernum = ' [ordernum] ' and
Type = 20")=20,-1,0))=0);
It's convoluted and very difficult to read. But it is saying, "If this job and order appears in JCCHANGEORDERSTEP with a type of 20, exclude it." So, that's what you need to fix.
The whole query should probably be fixed in a variety of ways. But I think this might get you where you need to go.
strSQL = "SELECT DISTINCT Sum(jcdetail.cost) AS SumOfcost " & _
"FROM jcchangeorder " & _
"INNER JOIN jcdetail " & _
"ON (jcchangeorder.ordernum = jcdetail.ponum) " & _
"AND (jcchangeorder.jobnum =jcdetail.jobnum) " & _
"GROUP BY jcdetail.jobnum, " & _
"jcdetail.type, " & _
"jcchangeorder.type, " & _
"DLookUp(""type"",""jcchangeorderstep"",""jobnum = '"" & [jcchangeorder].[jobnum] & ""' and ordernum = '"" & [ordernum] & ""' and Type = 1"") " & _
"HAVING (jcdetail.jobnum='" & strJ & "' AND " & _
"jcdetail.type=19 AND " & _
"jcchangeorder.type <> 2) AND " & _
"DLookUp(""type"",""jcchangeorderstep"",""jobnum = '"" & [jcchangeorder].[jobnum] & ""' and ordernum = '"" & [ordernum] & ""' and Type = 1"")=1;"
What I have done is changed to condition to say "If this job and order appears in JCCHANGEORDERSTEP with a type of 1, include it." Without actually seeing your data and testing the code myself, I can't promise this will work. There may be some typos, so I've explained what I'm trying to do, so you can fix them.
Also, take some time to go through the Stack Overflow tour. This community can be a great help if you work with it.
Try This:
After discussing the desired results with the OP, it appears that this would be a better solution. It gives the sum of all change orders that only have a change order step of PENDING.
strSQL = _
"SELECT SUM(JCD.cost) AS sumofcost " & _
"FROM jcchangeorder JCCO " & _
"INNER JOIN jcdetail JCD " & _
"ON JCCO.ordernum = jcd.ponum " & _
"AND JCCO.jobnum = jcd.jobnum " & _
"INNER JOIN (SELECT JCCOS.ponum, " & _
"JCCOS.jobnum " & _
"FROM jcchangeorderstep JCCOS " & _
"GROUP BY JCCOS.ponum, " & _
"JCCOS.jobnum " & _
"HAVING Count(*) = 1 " & _
"AND First(JCCOS.type) = 1) JCSELECT " & _
"ON JCCO.ordernum = JCSELECT.ponum " & _
"AND JCCO.jobnum = JCSELECT.jobnum " & _
"GROUP BY JCD.jobnum, " & _
"JCD.type, " & _
"JCCO.type "
"HAVING JCD.jobnum='" & strJ & "' AND " & _
"JCD.type=19 AND " & _
"JCCO.type <> 2;"
JCCO, JCCOS, and JCD are SQL aliases. SQL understands them. JCSELECT is an aliased subquery. JCSELECT creates a set of all job/orders that only have a step of PENDING.

access 2013 increasing quantity in a table field

Good day. I'm a little stumped about what is happening in my code. I have a userform which collects txtQntyRecd and cboSupplySource. I calculate the lookupValue. And it works just fine. It successfully places the txtQntyRecd in the correct tblWarehouseLocations.WQuantity location. The code is:
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = '" & Me.txtQntyRecd & "'" & _
"WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
CurrentDb.Execute updateQnty, dbFailOnError
What I want to do is add the next quantity to the same location. I get weird results if I change the SET statement to the following:
SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + '" & Me.txtQntyRecd & "'"
If I put 200 in the first statement, I get 200 in my WQuantity field. When I change to the second statement and I try to add 1 to the 200 I get a result of 211. If I add 1 again, the result is 223. Add 1 again, the result is 236.
Could someone explain what is happening and why the results aren't 201, 202 and 203? In the future I will need to subtract quantities from WQuantity as well.
Thanks
You're adding quotes around an integer and appending it as a string. Change it to:
".....
SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + " & val(Me!txtQntyRecd) & "....
...."
I've changed the . to a ! as I think it's still a nice distinction between objects properties and controls, and used the val function as it converts the string number value to the integer value.
This is your query in full:
' When I use values from controls, I like to store them in vars
Dim quantityReceived As integer
quantityReceived = val(Me!txtQntyRecd)
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = tblWarehouseLocations.WQuantity + " & quantityReceived & _
" WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
I solved the problem. I created a SELECT query to get the present amount in WQuantity. Now quantityReceived = Me!txtQntyRecd + the present amount. With SET tblWarehouseLocations.WQuantity = " & quantityReceived it works fine. However, if just seems so cumbersome.
' lookupValue gives the index into the tblWarehouseLocations where WQuantity resides
Dim lookupValue As Integer
lookupValue = DLookup("[WLocation_ID]", "[tblWarehouseLocations]", "[Location_Name] = '" & Me.cboWLocation & "'")
'Define SQL Query
strSQL = "select tblWarehouseLocations.WQuantity FROM tblWarehouseLocations WHERE (((tblWarehouseLocations.WLocation_ID)= " & lookupValue & "))"
Set rs = db.OpenRecordset(strSQL)
If IsNull(rs!WQuantity) Then
dbvalue = 0
Else
dbvalue = rs!WQuantity
End If
Dim quantityReceived As Integer
quantityReceived = Val(Me!txtQntyRecd) + dbvalue
updateQnty = "UPDATE tblSupplySources INNER JOIN ((tblWarehouseLocations " & _
"INNER JOIN tblSupplySource_WarehouseLocation ON tblWarehouseLocations.WLocation_ID = tblSupplySource_WarehouseLocation.SWLocation_ID)) " & _
"ON tblSupplySources.SupplySourceID = tblSupplySource_WarehouseLocation.Supply_Source_ID " & _
"SET tblWarehouseLocations.WQuantity = " & quantityReceived & _
" WHERE (((tblSupplySource_WarehouseLocation.Supply_Source_ID)= " & Me.cboSupplySource & ") " & _
" AND ((tblWarehouseLocations.WLocation_ID)=" & lookupValue & "))"
CurrentDb.Execute updateQnty, dbFailOnError

Using insert into where not exists in VBA

I have a lovely form and a lovely table in MS access (I promise). I would like to insert into this table at the press of a button using where not exists but I am getting a not-so-friendly run-time error 3067: "Query input must contain at least one table or query."
My query already does...
strSQL = "insert into tbl_MAP_systemTask (TaskID, SystemID) " & _
" Values (" & taskID & ", " & sysID & _
") where not exists " & _
" (select M.TaskID, M.SystemID from tbl_MAP_systemTask as M where M.TaskID = " & taskID & _
" and M.SystemID = " & sysID & ");"
Debug.Print strSQL
DoCmd.RunSQL (strSQL)
strSQL is now
insert into tbl_MAP_systemTask (TaskID, SystemID)
Values (1, 1)
where not exists
(select M.TaskID, M.SystemID
from tbl_MAP_systemTask as M where M.TaskID = 1 and M.SystemID = 1);
Can anyone shed any light on
a) what I broke?
b) how to fix it?
Well instead of using a SubQuery, you could use a Domain function to get this going,
If Dcount("*", "tbl_MAP_systemTask", "TaskID = " & taskID & " AND SystemID = " &sysID) = 0 Then
strSQL = "INSERT INTO tbl_MAP_systemTask (TaskID, SystemID) " & _
" VALUES (" & taskID & ", " & sysID & ")
CurrentDb.Execute strSQL
Else
MsgBox "The Data already exists in the table, so nothing was added."
End If
Try this:
strSQL = "insert tbl_MAP_systemTask (TaskID, SystemID) " & _
" select " & taskID & ", " & sysID & _
" where not exists " & _
" (select M.TaskID, M.SystemID from tbl_MAP_systemTask as M where M.TaskID = " & taskID & _
" and M.SystemID = " & sysID & ");"
=>
insert tbl_MAP_systemTask (TaskID, SystemID)
select 1, 1
where not exists
(select M.TaskID, M.SystemID
from tbl_MAP_systemTask as M where M.TaskID = 1 and M.SystemID = 1);
and seems to work in my case. Seems like the where not exists needs a select statement, so you have to model your insert like this.
Maybe you can use a recordset to insert these values.
Dim rs as Recordset
Set rs = Currentdb.openRecordset("SELECT * FROM tbl_MAP_systemTask WHERE TaskID=" & Me.TaskID & " AND SystemID=" & Me.SystemID)
if not (rs.eof or rs.bof) then
rs.addnew
rs.TaskID = Me.TaskID
rs.SystemID = Me.SystemID
rs.update
end if
rs.close
set rs = nothing
TOP 1 clause is must in the main query.
INSERT INTO tbl_MAP_systemTask (TaskID, SystemID)
SELECT TOP 1 1 AS TaskID 1 AS SystemID
FROM tbl_MAP_systemTask
WHERE NOT EXISTS (SELECT TOP 1 TaskID,SystemID FROM
tbl_MAP_systemTask WHERE TaskID = 1 and SystemID=1);
If tbl_MAP_systemTask table is empty or if there is only one record in the table then TOP 1 clause must be omitted in sub-query.
I have included Top 1 clause is sub-query for performance purpose.

Time out on Recordset with linked tables

Dim rt As DAO.Recordset
strSQL = "SELECT DISTINCT A.OBJ FROM "
strSQL = strSQL & "(SELECT VARBL AS OBJ FROM AGR_1252 WHERE AGR_NAME = '" _
& AGR & "') A LEFT JOIN "
strSQL = strSQL _
& "(SELECT DISTINCT CONF_USOBT_C_ORG.ORG_OBJECT AS OBJ FROM Role_Content, CONF_USOBT_C_ORG "
strSQL = strSQL & "WHERE Role_Content.AGR_NAME = '" _
& AGR & "' AND Role_Content.TCode = [CONF_USOBT_C_ORG].[Name] AND Role_Content.TCode <> '" & tc & "') B "
strSQL = strSQL & "ON A.OBJ = B.OBJ WHERE B.OBJ Is Null"
Set rt = CurrentDb.OpenRecordset(strSQL)
Do While Not rt.EOF
DoCmd.RunSQL "DELETE FROM AGR_1252 WHERE AGR_NAME = '" & AGR & "' AND VARBL = '" & rt("OBJ") & "'" ', False
rt.MoveNext
Loop
rt.Close
Set rt = Nothing
I have the code above. I dont know why but it's giving me a time out error on the while loop. I dont know if it if because of the Recordset, but the table is blocking after he mades the firts Delete.
There is another way to select records without using RecordSet?
Thanks in advance.
I think you may be looking for something on the lines of:
DELETE FROM AGR_1252
WHERE AGR_NAME = Agr
AND Varbl Not In (
SELECT c.ORG_OBJECT
FROM Role_Content r
INNER JOIN CONF_USOBT_C_ORG c
ON r.TCode =c.[Name]
WHERE r.AGR_NAME Is Null)