How do I add complex where clause to Zend Table Select? - zend-framework

I searched the Web and could not find anything that would show me a good solid example. My question is basically this:
How do I convert this:
SELECT * FROM table WHERE ((a = 1 AND b = 2) OR (c = 3 OR c = 4)) AND d = 5;
To Zend syntax similar to this:
$this
->select()
->from($this->_schema.'.'.$this->_name)
->where('a = ?', '1');
So how can it be done?
Thank a lot in advance.

I had a similar problem. See the code example in the answer here: Grouping WHERE clauses with Zend_Db_Table_Abstract
So you would end up with something like:
$db = $this->getAdapter();
$this->select()
->where('(' . $db->quoteInto('a = ?', 1) . ' AND ' . $db->quoteInto('b = ?', 2) . ') OR (' . $db->quoteInto('c = ?', 3) . ' OR ' . $db->quoteInto('c = ?', 4) . ')')
->where('d = ?', 5);
Which would give you:
SELECT `table_name`.* FROM `table_name` WHERE ((a = 1 AND b = 2) OR (c = 3 OR c = 4)) AND (d = 5)

1) Build a condition for all groups Where/orWhere:
$conditions = $this->select()
->where('a= ?', 5)
->orWhere('b= ?', 6)
->getPart(Zend_Db_Select::WHERE);
// result: $conditions = "(a= 5) OR (b= 6)";
Use getPart() method to get the where condition.
2) Next, reset the where part of current select object:
$this->select()->reset(Zend_Db_Select::WHERE);
3) Finally, use where condition as you want:
$this->select()
->where('d= ?', 5)
->where(implode(' ', $conditions));
http://framework.zend.com/manual/1.12/ru/zend.db.select.html

Per a message board post on the Zend Framework website, this may not be possible.
It seems to me that where() and orWhere() in the Zend_Db_Select class are not enough to be able to write all queries. It does not support the nesting of conditions, which doesn't enforce the user with abstraction in somewhat more complex cases. With where() and orWhere() I cannot write this:

Edit
The array functionality of Zend_Db_Select->where is designed only for using it with the IN clause.
Example #17 Example of an array parameter in the where() method
// Build this query:
// SELECT product_id, product_name, price
// FROM "products"
// WHERE (product_id IN (1, 2, 3))
$productIds = array(1, 2, 3);
$select = $db->select()
->from('products',
array('product_id', 'product_name', 'price'))
->where('product_id IN (?)', $productIds);
Original
As Peder said you can't nest orWhere but you can pass multiple arguments into where and orWhere.
$this->select()
->from($this->_schema.'.'.$this->_name)
->where(' ( a = ? AND b = ? ) OR ( c = ? OR c = ? ) ', array(1,2,3,4))
->where('d = ?',array(5));

Related

Zend Framework 1 SQL query Where

Is there any way to do something like this:
SELECT * FROM table WHERE p1=1 AND p2=2 AND ( p3 like %string1% OR p3 like %string3% )
In Zend Framework 1 by Zend_Db_Select or something else ?
Not sure about how you would go about doing such complex nested query using Zend_Db_Select but you can write can consider writing query manually as follows -
$sql = 'SELECT * FROM table WHERE p1 = ? AND p2 = ? AND (p3 LIKE ? OR p3 LIKE ?)';
$db->fetchAll($sql, [$p1, $p2, "%{$p3}%", "%{$p4}%"]);
You should rather use Zend_Db_Statement, which gives flexible options for fetching result sets. You can use:
$stmt = $db->query(
'SELECT * FROM table WHERE p1 = ? AND p2 = ? AND (p3 LIKE ? OR p3 LIKE ?',
array('1', '2', '%string1%', '%string3%')
);

Node-mysql: How to select with multiple OR in WHERE clause? How to create a query?

I receive such an array:
[1,2,3,4,5];
And I need to implement a query that has many ORs in WHERE clause. I take values from my array. It looks like this:
SELECT foo, bar FROM tbl WHERE (a.bar = 1 OR a.bar = 2 OR a.bar = 3 ... and so on)
How may I create such a WHERE part in node-mysql? Or how to pass it parameters?
I know this is fairly old, but I've had success, at least with recent versions of node-mysql using this format:
var titles = ['title 1', 'title 2'];
var sql = 'SELECT t.id ' +
' FROM topics t ' +
' WHERE t.title IN (?)';
var params = [titles];
This translates pretty nicely to:
SELECT t.id FROM topics t WHERE t.title IN (\'title 1\', \'title 2\')
Much cleaner, I think.
simple thing to do is to use the join() of the array
var values = [1, 2, 3, 4, 5];
var query = 'SELECT foo, bar FROM tbl WHERE (a.bar = ';
query = query + values.join(' OR a.bar = ') + ')';
That will generate the query you're looking for

Zend_DB subselect / subquery how to?

I have this raw sql statement which I am trying to execute through Zend_DB.
$sql = 'SELECT relocationaction.id, relocationaction.vehicle, relocationaction.start, relocationaction.end, relocationaction.return ' .
'FROM relocationaction,
(SELECT vehicle, MAX(end) AS maxend
FROM relocationaction
GROUP BY vehicle) AS co2
WHERE co2.vehicle = relocationaction.vehicle
AND(relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= ?)
AND relocationaction.end = co2.maxend';
I have found a possible solution using this type of notation, but it is rendered to a totally different and wrong sql statement with joins and strange table names.
$tbl = $this->getDbTable();
$select = $tbl->select()->setIntegrityCheck(false);
$subSelect = $select->from('relocationaction', array('vehicle', 'maxend' => 'MAX(relocationaction.end)'))
->group('vehicle');
$subSelectString = '(' . $subSelect->__toString() . ')';
$select ->from(
array('relocationaction'), array('id', 'date' => 'start', 'enddate' => 'end', 'return'),
array('co2' => $subSelectString)
)
->joinLeft('exhibitvehicle', 'exhibitvehicle.id = relocationaction.vehicle', array())
->where('co2.vehicle = relocationaction.vehicle')
->where('relocationaction.monitor = 1')
->where('relocationaction.return IS NULL')
->where('start <= ?', $start->get('yyyy-MM-dd'))
->where('relocationaction.end = co2.maxend');
Can anyone please give me a hint?
Thanks
Jesse
UPDATE
This is the result of the second expression (total rubbish)
SELECT `relocationaction`.`vehicle`,
MAX(relocationaction.end) AS `maxend`,
`relocationaction_2`.`id`,
`relocationaction_2`.`start` AS `date`,
`relocationaction_2`.`end` AS `enddate`,
`relocationaction_2`.`return`
FROM `relocationaction`
INNER JOIN `(
SELECT ``relocationaction``.``vehicle``,
MAX(relocationaction.end) AS ``maxend`` FROM ``relocationaction`` GROUP BY ``vehicle``)`.`relocationaction` AS `relocationaction_2`
LEFT JOIN `exhibitvehicle` ON exhibitvehicle.id = relocationaction.vehicle
WHERE (col2.vehicle = relocationaction.vehicle)
AND (relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= '2013-05-08')
AND (relocationaction.end = col2.maxend)
GROUP BY `vehicle`
If you use a string in from(), Zend_Db_Select will consider it to be a table name so it escapes it.
The solution is to wrap your subselect into a Zend_Db_Expr.
$tbl = $this->getDbTable();
$select = $tbl->select()->setIntegrityCheck(false);
$subSelect = $select->from('relocationaction', array('vehicle', 'maxend' => 'MAX(relocationaction.end)'))
->group('vehicle');
$subSelectString = '(' . $subSelect->__toString() . ')';
$select ->from(
array('relocationaction'), array('id', 'date' => 'start', 'enddate' => 'end', 'return'),
array('co2' => new Zend_Db_Expr($subSelectString))
)
->joinLeft('exhibitvehicle', 'exhibitvehicle.id = relocationaction.vehicle', array())
->where('co2.vehicle = relocationaction.vehicle')
->where('relocationaction.monitor = 1')
->where('relocationaction.return IS NULL')
->where('start <= ?', $start->get('yyyy-MM-dd'))
->where('relocationaction.end = co2.maxend');
Ok here we go. I tried hard to find a solution with Zend_Db_Table but failed big time. That's why I finally did it with PDO, as suggested by #user466764. Thanks for your help.
$tbl = $this->getDbTable();
$query = 'SELECT relocationaction.id,
relocationaction.vehicle,
relocationaction.start,
relocationaction.end,
relocationaction.return
FROM relocationaction
(SELECT vehicle, MAX(end) AS maxend
FROM relocationaction
GROUP BY vehicle) AS co2
WHERE co2.vehicle = relocationaction.vehicle
AND(relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= "' . $start->get('yyyy-MM-dd') . '")
AND relocationaction.end = co2.maxend';
$sth = $tbl->getAdapter()->prepare($query);
$sth->execute();
$entries = $sth->fetchAll();

OR clause in Zend DB update?

I'd like to do a Zend db update with an OR clause. What would be the equivalent statement to:
UPDATE mail
SET message_read = 1
WHERE id = 5
OR id = 10
When calling Zend_Db_Adapter::update(), multiple WHERE conditions will automatically be combined using AND (line 698 of Zend/Db/Adapter/Abstract.php in function _whereExpr).
You can get around this by creating your own Zend_Db_Expr which you will use as the WHERE condition and it will be left untouched.
For example:
$where[] = new Zend_Db_Expr(
$table->getAdapter()->quoteInto('id = ?', 5) . ' OR ' .
$table->getAdapter()->quoteInto('id = ?', 10)
);
// resulting expression:
// WHERE (id = 5 OR id = 10)
$table->update($data, $where);
If you had additional WHERE conditions, they would be combined with the OR condition by an AND.
Example:
$where[] = new Zend_Db_Expr(
$table->getAdapter()->quoteInto('id = ?', 5) . ' OR ' .
$table->getAdapter()->quoteInto('id = ?', 10)
);
$where[] = $table->getAdapter()->quoteInto('type = ?', 'sometype');
// resulting expression:
// WHERE (id = 5 OR id = 10) AND (type = 'sometype')
->where() will add a where clause to the query and will put an 'AND'. There is an orWhere method that exists to do that.
$select = $this->select();
$select->where('id = 5');
$select->orWhere('id = 10');
$this->fetchAll($select);

Multiple/nested "select where" with Zend_Db_Select [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Grouping WHERE clauses with Zend_Db_Table_Abstract
I need to create something like this:
select name from table where active = 1 AND (name LIKE 'bla' OR description LIKE 'bla')
The first part is easy:
$sqlcmd = $db->select()
->from("table", "name")
->where("active = ?", 1)
Now comes the tricky part. How can I nest? I know that I can just write
->orWhere("name LIKE ? OR description LIKE ?", "bla")
But thats wron, because I need to dynamically change all the parts. The query will be built all the time the script runs. Some parts get deleted, some altered. In this example I need to add those OR-s because sometimes I need to search wider.
"My Zend Logic" tells me that the correct way is like this:
$sqlcmd = $db->select()
->from("table", "name")
->where("active = ?", 1)
->where(array(
$db->select->where("name LIKE ?", "bla"),
$db->select->orWhere("description LIKE ?", "bla")
))
But that doesn't work (atleast I dont remember it working).
Please. Can someone help me to find a object oriented way for nesting "where"-s
Here's an example from the ZF manual
// Build this query:
// SELECT product_id, product_name, price
// FROM "products"
// WHERE (price < 100.00 OR price > 500.00)
// AND (product_name = 'Apple')
$minimumPrice = 100;
$maximumPrice = 500;
$prod = 'Apple';
$select = $db->select()
->from('products',
array('product_id', 'product_name', 'price'))
->where("price < $minimumPrice OR price > $maximumPrice")
->where('product_name = ?', $prod);
It should fit your needs
To build this query:
SELECT product_id, product_name, price
FROM "products"
WHERE (price > 100.00)
AND (price < 500.00)
use this code:
$minimumPrice = 100;
$maximumPrice = 500;
$select = $db->select()
->from('products',
array('product_id', 'product_name', 'price'))
->where('price > ?', $minimumPrice)
->where('price < ?', $maximumPrice);