use joins in zend framework query - zend-framework

I want to use joins in zend. Below is my query
$select = $this->_db->select()
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications','tendersupplier' => 'tblsupplier'),
'tenderapplications. TenderInvitationContractorID=tendersupplier.UserID');
I have UserID in tendersupplier table. but its giving following error :-
Column not found: 1054 Unknown column 'tendersupplier.UserID' in 'on clause

I think its not the right way to include more than one tale in same array of a join.
Try code like this..
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications'),
'tenderapplications.TenderInvitationContractorID=tblsupplier.UserID');
I am not sure whether you are planning to join values from tblsupplier table also.

The where condition is not written the way you did .
I dount that tblsupplier is a table then it should be in an array
This code is not tested!
$select = $this->_db->select()
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications'), array('tendersupplier' => 'tblsupplier'))
->where('tenderapplications. TenderInvitationContractorID=tendersupplier.UserID');

Looks like you are trying to join 2 tables in one ->join, I don't think you can do that.
join code from Zend_Db_Select()
/**
* Adds a JOIN table and columns to the query.
*
* The $name and $cols parameters follow the same logic
* as described in the from() method.
*
* #param array|string|Zend_Db_Expr $name The table name.
* #param string $cond Join on this condition.
* #param array|string $cols The columns to select from the joined table.
* #param string $schema The database name to specify, if any.
* #return Zend_Db_Select This Zend_Db_Select object.
*/
public function join($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
{
return $this->joinInner($name, $cond, $cols, $schema);
}
Here is the comment block from from()
/**
* Adds a FROM table and optional columns to the query.
*
* The first parameter $name can be a simple string, in which case the
* correlation name is generated automatically. If you want to specify
* the correlation name, the first parameter must be an associative
* array in which the key is the correlation name, and the value is
* the physical table name. For example, array('alias' => 'table').
* The correlation name is prepended to all columns fetched for this
* table.
*
* The second parameter can be a single string or Zend_Db_Expr object,
* or else an array of strings or Zend_Db_Expr objects.
*
* The first parameter can be null or an empty string, in which case
* no correlation name is generated or prepended to the columns named
* in the second parameter.
*
* #param array|string|Zend_Db_Expr $name The table name or an associative array
* relating correlation name to table name.
* #param array|string|Zend_Db_Expr $cols The columns to select from this table.
* #param string $schema The schema name to specify, if any.
* #return Zend_Db_Select This Zend_Db_Select object.
*/
Maybe try something like this instead:
$select = $this->_db->select()
//FROM table procurement_tbltenderevaluationcriteria AS evaluationcriteria, SELECT FROM
//COLUMNS ScoringCriteriaID and ScoringCriteriaWeight
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
//JOIN TABLE procurement_tbltenderscoringcriteria AS scoringcriteria WHERE
//TenderId FROM TABLE scoringcriteria == TenderId FROM TABLE evaluationcriteria
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria.TenderId=evaluationcriteria.TenderId')
//JOIN TABLE procurement_tbltenderapplications AS tenderapplications
->join(array('tenderapplications' => 'procurement_tbltenderapplications'))
//JOIN TABLE tblsupplier AS tendersupplier WHERE TenderInvitationContractorID FROM TABLE
// tenderapplications == UserID FROM TABLE tendersupplier
->join(array('tendersupplier' => 'tblsupplier'),
'tenderapplications.TenderInvitationContractorID=tendersupplier.UserID');
you may also need to alter your select() definition to allow joins:
//this will lock the tables to prevent data corruption
$this->_db->select(Zend_Db_Table::SELECT_WITHOUT_FROM_PART)->setIntegrityCheck(FALSE);
I hope I'm reading your intent correctly, this should get you closer if not all the way there. (one hint, use shorter aliases...)

Related

Scala Spark Replace empty String with NULL

What I want here is to replace a value in a specific column to null if it's empty String.
The reason is I am using org.apache.spark.sql.functions.coalesce to fill one of the Dataframe's column based on another columns, but I have noticed in some rows the value is empty String instead of null so the coalesce function doesn't work as expected.
val myCoalesceColumnorder: Seq[String] = Seq("xx", "yy", "zz"),
val resolvedDf = df.select(
df("a"),
df("b"),
lower(org.apache.spark.sql.functions.coalesce(myCoalesceColumnorder.map(x => adjust(x)): _*)).as("resolved_id")
)
In the above example, I expected to first fill resolved_id with column xx if it' not null and if it's null with column yy and so on. But since sometime column xx is filled with "" instead of null I get "" in 'resolved_id'.
I have tried to fix it with
resolvedDf.na.replace("resolved_id", Map("" -> null))
But based on the na.replace documentation it only works if both key and value are either Bolean or String or Double so I can not use null here.
I don't want to use UDF because of the performance issue, I just want to know is there any other trick to solve this issue?
One other way I can fix this is by using when but not sure about the performance
resolvedDf
.withColumn("resolved_id", when(col("resolved_id").equalTo(""), null).otherwise(col("resolved_id")))
This is the right way with better performance
resolvedDf.withColumn("resolved_id", when($"resolved_id" =!= "", $"resolved_id"))
Basically no need to use otherwise method.
You can check sources::: https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/Column.scala#L507
/**
* Evaluates a list of conditions and returns one of multiple possible result expressions.
* If otherwise is not defined at the end, null is returned for unmatched conditions.
*
* {{{
* // Example: encoding gender string column into integer.
*
* // Scala:
* people.select(when(people("gender") === "male", 0)
* .when(people("gender") === "female", 1)
* .otherwise(2))
*
* // Java:
* people.select(when(col("gender").equalTo("male"), 0)
* .when(col("gender").equalTo("female"), 1)
* .otherwise(2))
* }}}
*
* #group expr_ops
* #since 1.4.0
*/
def when(condition: Column, value: Any): Column = this.expr match {
case CaseWhen(branches, None) =>
withExpr { CaseWhen(branches :+ ((condition.expr, lit(value).expr))) }
case CaseWhen(branches, Some(_)) =>
throw new IllegalArgumentException(
"when() cannot be applied once otherwise() is applied")
case _ =>
throw new IllegalArgumentException(
"when() can only be applied on a Column previously generated by when() function")
}

Comparing two fileds in select command

I am trying to select all records from Transaction_Table where Tr_Amount = Instrument_Number using following Code
Select * from Transaction_Table
where abs(Tr_Amount) = Cast(Instrument_number as INTEGER)
However there are some rows in the table where Instrument_Number is Alphanumeric instead of Just Numeric Data. I there a way to skip the alphanumeric instances in Instrument_Number field in the command.
Switch to TO_NUMBER, which returns NULL for bad data:
Select * from Transaction_Table
where abs(Tr_Amount) = TO_NUMBER(Instrument_number)
TD15.10 implements a TRYCAST:
Select * from Transaction_Table
where abs(Tr_Amount) = TRY_CAST(Instrument_number as INTEGER)

Symfony2 Doctrine - ILIKE clause for PostgreSQL?

I'm currently using symfony2, doctrine 2.3 and PostgreSQL 9. I've been searching for a couple of hours now to see HOW on earth do I do a ILIKE select with QueryBuilder.
It seems they only have LIKE. In my situation, though, I'm searching case-insensitive.
How on earth is it done?
// -- this is the "like";
$search = 'user';
$query = $this->createQueryBuilder('users');
$query->where($query->expr()->like('users.username', $query->expr()->literal('%:username%')))->setParameter(':username', $search);
// -- this is where I get "[Syntax Error] line 0, col 86: Error: Expected =, <, <=, <>, >, >=, !=, got 'ILIKE'
$search = 'user';
$query = $this->createQueryBuilder('users');
$query->where('users.username ILIKE :username')->setParameter(':username', $search);
I don't know about Symfony, but you can substitute
a ILIKE b
with
lower(a) LIKE lower(b)
You could also try the operator ~~*, which is a synonym for ILIKE
It has slightly lower operator precedence, so you might need parenthesis for concatenated strings where you wouldn't with ILIKE
a ILIKE b || c
becomes
a ~~* (b || c)
The manual about pattern matching, starting with LIKE / ILIKE.
I think this guy had the same problem and got an answer:
http://forum.symfony-project.org/viewtopic.php?f=23&t=40424
Obviously, you can extend Symfony2 with SQL vendor specific functions:
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/cookbook/dql-user-defined-functions.html
I am not a fan of ORMs and frameworks butchering the rich functionality of Postgres just to stay "portable" (which hardly ever works).
This works for me (Symfony2 + Doctrine 2)
$qq = 'SELECT x FROM MyBundle:X x WHERE LOWER(x.y) LIKE :y';
$q = $em->createQuery($qq)->setParameter(':y', strtolower('%' . $filter . '%'));
$result = $q->getResult();
Unfortunately, we still do not have the ability to create custom comparison operators...
But we can create a custom function in which we implement the comparison.
Our DQL query well look like this:
SELECT q FROM App\Entity\Customer q WHERE ILIKE(q.name, :name) = true
The class describing the ILIKE function will look like this:
class ILike extends FunctionNode
{
/** #var Node */
protected $field;
/** #var Node */
protected $query;
/**
* #param Parser $parser
*
* #throws \Doctrine\ORM\Query\QueryException
*/
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->field = $parser->StringExpression();
$parser->match(Lexer::T_COMMA);
$this->query = $parser->StringExpression();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
/**
* #param SqlWalker $sqlWalker
*
* #return string
* #throws \Doctrine\ORM\Query\AST\ASTException
*/
public function getSql(SqlWalker $sqlWalker)
{
return '(' . $this->field->dispatch($sqlWalker) . ' ILIKE ' . $this->query->dispatch($sqlWalker) . ')';
}
}
The resulting SQL will look like this:
SELECT c0_.id AS id_0,
c0_.name AS name_1,
FROM customer c0_
WHERE (c0_.name ILIKE 'paramvalue') = true
From what I am aware, search queries in Symfony2 (at least when using Doctrine) are case in-sensitive. As noted in the Doctrine QL docs:
DQL is case in-sensitive, except for namespace, class and field names, which are case sensitive.

Zend DB fetchAll(): where as array

I'm confused as to why Zend_DB doesn't accept an array of WHERE clauses - or am I incorrect? I have made the following work around:
$all = new ORM_Model_DbTable_Asset();
$wheres = array('id > 0', 'enabled' => 1);
$all = $all->fetchAll(implode(' AND ', $wheres))->toArray();
for what I hoped would be:
$all = new ORM_Model_DbTable_Asset();
$wheres = array('id > 0', 'enabled' => 1);
$all = $all->fetchAll($wheres)->toArray();
Slightly disappointing, am I missing something?
From Zend_Db_Table_Abstract
/**
* Fetches all rows.
*
* Honors the Zend_Db_Adapter fetch mode.
*
* #param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
* #param string|array $order OPTIONAL An SQL ORDER clause.
* #param int $count OPTIONAL An SQL LIMIT count.
* #param int $offset OPTIONAL An SQL LIMIT offset.
* #return Zend_Db_Table_Rowset_Abstract The row results per the Zend_Db_Adapter fetch mode.
*/
public function fetchAll($where = null, $order = null, $count = null, $offset = null)
So you are incorrect, fetchAll() does accept an array of where clauses.
Your array should look like this (based on the definition in Zend_Db_Select)
$where = array(
'id > 0',
'enabled = ?' => 1
);
First we will look at your original code:
$wheres = array('id > 0', 'enabled' => 1);
Remember that => is an assignment operator. In your array above you start out with string automatically assigned to key 0. The next element is the number 1 assigned to the key 'enabled'. The solution proposed in answer 1 assigns the number 1 to key 'enabled = ?'.
Try this:
$all = new ORM_Model_DbTable_Asset();
$where = array();
$where[] = 'id > 0';
$where[] = $all->quote_into('enabled >= ?', 1, 'INTEGER'); // 1 could be a variable
$result = $all->fetchAll($where);

Zend_DB_Select : why are all fields returned?

public function getWorksheetData($id) {
/** create the following query using select object:
SELECT wc.label, wd.notes FROM worksheet_data wd
LEFT JOIN worksheet_columns wc ON wd.column_id = wc.id;
*/
$id = (int) $id;
$select = $this->_db->select()
->from(array('wd'=>'worksheet_data'),
array('wc.label','wd.notes'))
->join(array('wc'=>'worksheet_columns','wd.column_id = wc.id'))
->where("wd.id = :worksheet_id");
$results = $this->_db->fetchAll($select, array('worksheet_id' => $id),Zend_Db::FETCH_ASSOC);
return array('results'=>$results);
}
Why does this query become:
SELECT wc.label, wd.notes, wc.* FROM worksheet_data AS wd INNER JOIN worksheet_columns AS wc WHERE (wd.id = :worksheet_id)
and return wc.*?
You need to put an empty array as the third argument to the join method, also the join condition should not be part of the first argument's array, but as the second argument instead (you'll notice that there is not join condition in your query). Join needs at least the first two arguments, this is the method signature:
join(table, join, [columns])
Applying that to your join method:
->join(array('wc'=>'worksheet_columns'),'wd.column_id = wc.id', array())
so:
$select = $this->_db->select()
->from(array('wd'=>'worksheet_data'),
array('wc.label','wd.notes'))
->join(array('wc'=>'worksheet_columns'),'wd.column_id = wc.id', array())
->where("wd.id = :worksheet_id");
gives the output:
SELECT `wc`.`label`, `wd`.`notes` FROM `worksheet_data` AS `wd` INNER JOIN `worksheet_columns` AS `wc` ON wd.column_id = wc.id WHERE (wd.id = :worksheet_id)
The manual says:
To select no columns from a table, use
an empty array for the list of
columns.