Динамическое где условие генерации в скале - PullRequest
0 голосов
/ 31 октября 2018

Я должен сгенерировать, где условие основано на классе дела / фрейме данных.

Например, у меня будут примерные данные, как показано ниже, которые я могу получить из класса дел / фрейма данных с 4 столбцами, у этого фрейма данных есть много данных, я должен фильтровать на основе идентификатора. для идентификатора я должен сгенерировать whereQuery

столбцы (id, col1, col2, col3)

|-------------------------------------------------------|
|id      |      col1     |      col2     |      col3    |
|-------------------------------------------------------|
|"1"     |   "col1vr1"   |   "col2vr1"   |   "col3vr1"  |
|"1"     |   "col1vr2"   |   "col2vr2"   |   "col3vr2"  |
|-------------------------------------------------------|

Для приведенных выше данных я должен сгенерировать предложение where, как показано ниже,

( col("col1")<=>col1vr1 &&  col("col2")<=>col2vr1 && col("col3") <=> col3vr1 ) ||  ( col("col1")<=>col1vr2 &&  col("col2")<=>col2vr2 && col("col3") <=> col3vr2 )

, чтобы я мог применить вышеуказанный запрос к условию WHEN when( finalColumn, "We don't have any records for this rule" ) // Здесь finalColumn генерирует запрос

Я пытался, как показано ниже

case class test(id: String, col1: String, col2: String, col3: String)

Данные испытаний:

 val testmap = List(
 test("1", "col1v", "col2va", "col3va"),
 test("1", "col1v", "col2va", "col3vb"),
 test("1", "col1va", "col2va", "col3vc"),
 test("1", "col1va", "col2va", "col3vd"),
  test("1", "col1vb", "col2vb", "col3vd"),
  test("1", "col1vb", "col2vb", "col3ve"),
  test("1", "col1vb", "col2va", "col3vd"),
  test("1", "col1vb", "col2va", "col3vf"),
  test("1", "col1vc", "col2vb", "col3vf"),
  test("1", "col1vc", "col2vc", "col3vf"),
  test("2", "col1v", "col2va", "col3va"),
  test("2", "col1v", "col2va", "col3vb"),
  test("2", "col1vb", "col2vb", "col3ve"),
  test("2", "col1vb", "col2vb", "col3vd"),
  test("2", "col1vc", "col2vc", "col3vf"),
  test("3", "col1va", "col2va", "col3va"),
  test("3", "col1vb", "col2vb", "col3vb"),
  test("3", "col1vc", "col2vc", "col3vc") )

Код Sinippet:

var whereCond = scala.collection.mutable.ArrayBuffer[Column]()
  val t1 = testmap.filter( p => p.id.equalsIgnoreCase("1") )    //This will call by iteration, we need rule per iteration
  t1.map( rule =>  {
   if ( ! (  rule.col1.equalsIgnoreCase("all") ) )  {
      whereCond.+=(col("col1")<=>rule.col1 + " && ") 
   if ( ! ( rule.col2.equalsIgnoreCase("all") ) )  {
      whereCond.+=(col("col2")<=>rule.col2 + " && ")
    }
   if ( !( rule.col3.equalsIgnoreCase("all") ) ) {
      whereCond.+=(col("col3")<=>rule.col3 + "  || ")
    }
  }
 })
 var finalColumn = col("")
 whereCond.toArray[Column].map(c => { finalColumn.+=(c) } )
 finalColumn    

Но не получаю ожидаемых результатов

А также, я попробовал ниже фрагмент кода тоже

  var columnData =  col("")
  val df = testmap.toDF.where($"id"<=>"3").distinct
  val col1List = df.select("col1").rdd.map(r=>       r.getString(0)).collect().toList
  val col2List = df.select("col2").rdd.map(r=> r.getString(0)).collect().toList
  val col3List = df.select("col3").rdd.map(r=> r.getString(0)).collect().toList
  for( i <- 0 to col1List.size - 1 )
    if ( columnData  == col("")) 
        columnData  =  col("col1")<=>col1List(i)  && col("col2")<=>col2List(i) &&  col("col3") <=>col3List(i) 
      else
        columnData  = columnData  || (col("col1")<=>col1List(i)  && col("col2")<=>col2List(i) &&  col("col3") <=>col3List(i)  )
  columnData

Всякий раз, когда мы делаем && или || операция на col scala, автоматически создающая скобки для них обоих

Для приведенного выше кода я получаю вывод, как показано ниже

    (((((col1 <=> col1vc) AND (col2 <=> col2vc)) AND (col3 <=> col3vc)) 
    OR (((col1 <=> col1va) AND (col2 <=> col2va)) AND (col3 <=> col3va))) 
    OR (((col1 <=> col1vb) AND (col2 <=> col2vb)) AND (col3 <=> col3vb))) 

Но я ожидаю вывод как

    col1 <=> col1vc AND col2 <=> col2vc AND col3 <=> col3vc 
    OR (col1 <=> col1va AND col2 <=> col2va AND col3 <=> col3va )
    OR (col1 <=> col1vb AND col2 <=> col2vb AND col3 <=> col3vb )

1 Ответ

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

Всякий раз, когда мы делаем && или || операция на col scala, автоматически создающая скобки для них обоих

Это не Скала. Это простой приоритет оператора SQL, где ( цитирование ответа от charles-bretana ):

И имеет приоритет над Или, поэтому, даже если a <=> a1 Или a2

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

scala> import org.apache.spark.sql.functions.col
import org.apache.spark.sql.functions.col

scala> val col1 = col("col1")
col1: org.apache.spark.sql.Column = col1

scala> val col2 = col("col2")
col2: org.apache.spark.sql.Column = col2

scala> val col3 = col("col3")
col3: org.apache.spark.sql.Column = col3

scala> (col1 <=> "col1vc" and col2 <=> "col1vc")
res0: org.apache.spark.sql.Column = ((col1 <=> col1vc) AND (col2 <=> col1vc))

scala> col1 <=> "col1vc" and col2 <=> "col1vc" and col3 <=> "col3vc"
res1: org.apache.spark.sql.Column = (((col1 <=> col1vc) AND (col2 <=> col1vc)) AND (col3 <=> col3vc))

scala> col1 <=> "col1vc" and col2 <=> "col1vc" and (col3 <=> "col3vc" or (col1 <=> "col1va" and col2 <=> "col2va" and col3 <=> "col3va"))
res2: org.apache.spark.sql.Column = (((col1 <=> col1vc) AND (col2 <=> col1vc)) AND ((col3 <=> col3vc) OR (((col1 <=> col1va) AND (col2 <=> col2va)) AND (col3 <=> col3va))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...