Функция SQL / ACCESS не работает по назначению - PullRequest
0 голосов
/ 14 ноября 2018
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

Итак, меня бросили в какую-то базу данных MS-Access со всеми операторами VBA / SQL.Я буквально новичок, но мне удалось кое-что выяснить и ознакомиться с нашей базой данных, которую мы используем для распечатки отчетов о работе.Некоторые функции вызова настроены неправильно и извлекают данные из неправильных таблиц, и мне в основном нужна помощь, чтобы выяснить, каким образом мне следует решить эту проблему.

В настоящее время, если мы запустим отчет ивызывает " GetPendingChangeOrders ", он делает то, что должен делать, но когда мы смотрим на то, что находится в стадии ожидания.Он показывает результат, даже если он имеет статус 21 (ОТКЛ.) Внутри таблицы "JCCHANGEORDERSTEP".Я включил изображения этого.

JCCHANGEORDER имеет то же самое, что и столбцы с JCCHANGEORDERSTEP (JOBNUM, ORDERNUM, TYPE), но типы в JCCHANGEORDER просто имеют тип 1, который, я полагаю, говорит, что я активен.

JCCHANGEORDERSTEP содержит 1 инициированных (ожидающих), 20 (утвержденных), 21 (запрещенных).Он отфильтровывает 20-е из результатов в отчете, но не 21. Поэтому мне просто нужна помощь и объяснение того, почему просто добавить 21 в микс не сработало.

Спасибо за ваше время.

РЕДАКТИРОВАТЬ-1 ДОБАВЛЕННЫЕ ИЗОБРАЖЕНИЯ ФОТОГРАФИИ ДОСТУПА К IMGUR

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Посмотрев на ваши изображения и изучив существующий код SQL, я думаю, что следующий запрос SQL может быть более подходящим и в целом более читабельным:

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

Здесь добавлено jcdetail записей, для которыхjcchangeorderstep.type = 1 обрабатывается inner join между таблицами, а не отдельным dlookup для каждой записи.

Вы можете реализовать это в своей функции следующим образом:

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

РЕДАКТИРОВАТЬ:

После последующих комментариев, кажется, более соответствует вашим требованиям:

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
    )

Это может быть реализовано в вашей функции VBA следующим образом:

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
0 голосов
/ 14 ноября 2018

Эта часть запроса в предложениях HAVING и GROUP BY создает проблемы:

IIf(DLookUp("type",
            "jcchangeorderstep",
            "jobnum = ' [jcchangeorder].[jobnum] ' and 
              ordernum = ' [ordernum] ' and
              Type = 20")=20,-1,0))=0);

Это запутанно и очень трудно читать. Но он говорит: «Если это задание и порядок появляются в JCCHANGEORDERSTEP с типом 20, исключите его». Вот что вам нужно исправить.

Весь запрос, вероятно, должен быть исправлен различными способами. Но я думаю, что это может привести вас туда, куда вам нужно.

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;"

То, что я сделал, сменилось условием: «Если это задание и порядок отображаются в JCCHANGEORDERSTEP с типом 1, включите его». Не видя ваших данных и не тестируя код самостоятельно, я не могу обещать, что это сработает. Могут быть некоторые опечатки, поэтому я объяснил, что я пытаюсь сделать, чтобы вы могли их исправить.

Кроме того, потратьте некоторое время, чтобы пройти тур Stack Overflow. Это сообщество может оказать большую помощь, если вы работаете с ним.

Попробуйте:
После обсуждения желаемых результатов с ОП выясняется, что это будет лучшим решением. Он дает сумму всех заказов на изменение, которые только имеют шаг заказа на изменение 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 и JCD - псевдонимы SQL. SQL понимает их. JCSELECT является псевдонимом подзапроса. JCSELECT создает набор всех заданий / заказов, которые имеют только шаг PENDING.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...