Действительно ли возможно создать рекурсивный запрос в Доступе?

Проблема с вашим приложением foldLeft заключается в том, что оно не эквивалентно выражению, которое вы хотите использовать.

Как вы уже сказали, вы ищете

sha2(b, 256) = b_hash OR sha2(c, 256) = c_hash OR sha2(d, 256) = d_hash

, в то время как цепочечный фильтр на DataFrame приводит к

sha2(b, 256) = b_hash AND sha2(c, 256) = c_hash AND sha2(d, 256) = d_hash

Чтобы достичь первого, вы должны изменить аккумулятор:

import org.apache.spark.sql.functions.{col, lit}
import org.apache.spark.sql.Column

val atLeastOneMatch: Column = map.foldLeft(lit(false)) { 
  case (acc, (c, h)) => acc or (sha2(col(c), 256) === h) 
}

и затем использовать результат для фильтрации данных

df.filter(atLeastOneMatch).count

Это будет считать все строки , где хотя бы один столбец соответствует хешу предоставлено в map. По законам Де Моргана его отрицание

!atLeastOneMatch

будет эквивалентно

sha2(b, 256) != b_hash AND sha2(c, 256) != c_hash AND sha2(d, 256) = d_hash

Другими словами, оно будет соответствовать случаям, когда ни одно из значений не соответствует соответствующему хешу. [+1139]

Если вы хотите найти строки, в которых хотя бы одно значение не соответствует хешу , вам следует использовать

sha2(b, 256) != b_hash OR sha2(c, 256) != c_hash OR sha2(d, 256) != d_hash

, который можно составить, как показано ниже

[ 117]

Это отрицание

!atLeastOneMismatch

эквивалентно (законы де Моргана еще раз)

sha2(b, 256) = b_hash AND sha2(c, 256) = c_hash AND sha2(d, 256) = d_hash

и далее эквивалентно foldLeft с аккумулятором DataFrame и === . [тысяча сто сорок четыре]

Итак, подведем итог - если C является набором столбцов, то:

  • ∈c∈C map (c) = sha2 (c, 256) - atLeastOneMatch
  • ∀c∈C map (c)! = Sha2 (c, 256) - !atLeastOneMatch
  • ∃c∈C map ( c)! = sha2 (c, 256) - atLeastOneMismatch
  • ∀c∈C map (c) = sha2 (c, 256) - !atLeastOneMismatch [1131 ]

18
задан Martin F 8 April 2015 в 18:03
поделиться

3 ответа

Нет, это не так. Рекурсивные запросы поддерживаются в SQL Server после SServer 2005, но не в Access.

Если вы заранее знаете количество уровней, вы можете написать запрос, но он не будет рекурсивным.

В SQL Server Для этого используется CTE (расширение SQL): см. http://blog.crowe.co.nz/archive/2007/09/06/Microsoft-SQL-Server-2005---CTE-Example- of-a-simple.aspx

Однако обычный SQL не имеет поддержки рекурсивности.

8
ответ дан 30 November 2019 в 06:59
поделиться

Вы не можете рекурсивно запрашивать.

Вы можете сделать произвольное количество левых соединений, но вы ' Я смогу подняться только на столько уровней, сколько у вас есть объединений.

Или вы можете использовать «Модель вложенного набора» Челко , чтобы получить всех родителей. Это потребует изменения структуры таблицы таким образом, чтобы сделать вставки и обновления более сложными.

4
ответ дан 30 November 2019 в 06:59
поделиться

В Access можно создать запрос, чтобы найти корень вашего заданного задания. Не забывайте о мощи функций VBA .Вы можете создать рекурсивную функцию в модуле VBA и использовать ее результат в качестве поля вывода в своем запросе.

Пример:

Public Function JobRoot(Id As Long, ParentId As Long) As Long
   If ParentId = 0 Then
      JobRoot = Id
      Exit Function
   End If

   Dim Rst As New ADODB.Recordset
   Dim sql As String
   sql = "SELECT Id, ParentID FROM JobTable WHERE Id = " & ParentId & ";"
   Rst.Open sql, CurrentProject.Connection, adOpenKeyset, adLockReadOnly

   If Rst.Fields("ParentID") = 0 Then
      JobRoot = Rst.Fields("Id")
   Else
      JobRoot = JobRoot(Id, Rst.Fields("ParentID"))    ' Recursive.
   End If

   Rst.Close
   Set Rst = Nothing
End Function

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

Это даст корень.

(Я понимаю, что OP исполнился год, но я вынужден ответить, когда все говорят, что невозможное возможно).

26
ответ дан 30 November 2019 в 06:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: