简体   繁体   中英

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM