I have this Sql code:
( SELECT `column1` FROM `table_1` WHERE `column2` > 2 )
UNION
( SELECT `column1` FROM `table_2` WHERE `column2` < 10 )
ORDER BY `column1` ASC;
How to do that with Zend Framework 2?
Zend Framework 2 Zend\Db\Sql does not provide a Union method yet you'll have to either write it yourself or use a JOIN.
$sql = new Sql($this->adapter);
$select = $sql->select();
$select->from($this->table)
->join('table_1', 'table_2.column1 = table_1.column1');
$where = new Where();
$where->greaterThan('column2', 2) ; //youll have to add a and here with a lessThan
$select->where($where);
$statement = $sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
Honestly speaking I did not try this example, but it should atleast give you a Idea.
Related
I've converted the following query in Zend framework way
SELECT
DISTINCT
eva.errata_number, eva.headline, err.owner,err.rootCause, err.description FROM
v_allevaluations eva, erratas err
WHERE
eva.errata_number=err.errata_number and stateCombined = 'Affected' &&
(Select releases_id in (SELECT release_id
FROM subscription WHERE user_id = 83) OR folder in (SELECT folder
FROM subscribed_ns WHERE user_id = 83))
Zend framework query:
$select = $db->select()
->distinct()
->from(array('eva'=>'v_allevaluations'),array('errata_number', 'headline'))
->join(array('err'=>'erratas'), 'eva.errata_number= err.errata_number',array('owner','rootCause','description'))
->where('stateCombined=?','Affected')
->where('select releases_id IN (?)', new Zend_Db_Expr("SELECT release_id FROM subscription WHERE user_id = ".$user_id.") OR folder in (SELECT folder
FROM subscribed_ns WHERE user_id = ".$user_id.")"));
When I print $select it prints
SELECT
DISTINCT
`eva`.`errata_number`, `eva`.`headline`, `err`.`owner`, `err`.`rootCause`, `err`.`description`
FROM
`v_allevaluations` AS `eva` INNER JOIN `erratas` AS `err` ON eva.errata_number= err.errata_number
WHERE
(stateCombined='Affected')
AND
(select releases_id IN (SELECT release_id FROM subscription WHERE user_id = 83) OR folder in (SELECT folder FROM subscribed_ns WHERE user_id = 83)))
It adds an extra bracket at the end after user_id = 83.
Could you please let me know what is wrong?
I assigned sub-queries to a variable and replaced it in the query
$select = $db->select()
->distinct()
->from(array('eva'=>'v_allevaluations'),array('errata_number', 'headline'))
->join(array('err'=>'erratas'), 'eva.errata_number= err.errata_number',array('owner','rootCause','description'))
->where('stateCombined=?','Affected')
->where('select releases_id IN (?)', new Zend_Db_Expr(" ".$get_subscribed_release_ids." ) OR folder in (".$get_subscribed_folders.""));
Sub queries:
$get_subscribed_release_ids = $db->select()
->from(array('subscription'), 'release_id')
->where('user_id =?',"$user_id");
$get_subscribed_folders = $db->select()
->from(array('subscribed_ns'), 'folder')
->where('user_id =?',"$user_id");
the thing is that i don know if there is a way to get a value from a subquery over an update operation, the query that i'm trying to do looks like this, on a example code of my model :
$query = "UPDATE some_table SET value_1 = ((SELECT value_2 FROM other_table WHERE id = 2) + 1) WHERE id = 2";
$this->db->query($query);
i hope you can help me or at least let me know an alternative way to get this using the active record
PD i'm working with the CodeIgniter Framework
The equivalent of
UPDATE some_table SET value_1 = ((SELECT value_2 FROM other_table WHERE id = 2) + 1) WHERE id = 2
in ActiveRecord is probably:
$value_2 = $this->db->get_where('other_table', array('id' => 2))[0];
$data = array('value_1', $value_2 + 1);
$this->db->update('some_table', $data, array('id' => 2));
I not working with Codeigniter, but try this:
$query = "UPDATE some_table st SET st.value_1 = ((SELECT ot.value_2 FROM other_table ot WHERE ot.id = 2) + 1) WHERE st.id = 2";
$this->db->query($query);
Hi I want to convert my normal mysql query to zend.db.select;
I want to use this script:
$select = $db->select();
// Add a FROM clause
$select->from( ...specify table and columns... )
// Add a WHERE clause
$select->where( ...specify search criteria... )
// Add an ORDER BY clause
$select->order( ...specify sorting criteria... );
$select->limit(20, 10);
for my query below
SELECT
IF(derived_messages.toid = '$user', derived_messages.fromid,
derived_messages.toid) friend1,c.UserName,
derived_messages.message, derived_messages.fromid, derived_messages.toid,
derived_messages.is_read,derived_messages.type,derived_messages.id as mesid,
derived_messages.date,
(SELECT M.message_id FROM messagesmapped M where M.message_id= derived_messages.id AND M.user_id ='$user' AND M.important = 1) as MesMapid
FROM
(
SELECT *
FROM messages
WHERE messages.deleted_by NOT
IN ( $user )
ORDER BY Date DESC
) derived_messages
INNER JOIN Users c ON c.MemberID = IF(derived_messages.toid = '$user', derived_messages.fromid,
derived_messages.toid)
WHERE (derived_messages.id IN
(SELECT M.message_id FROM messagesmapped M where M.message_id= derived_messages.id AND M.user_id ='$user' AND M.important = 1)
AND
(derived_messages.toid='$user' OR derived_messages.fromid='$user'))
GROUP BY friend1 ASC
ORDER BY derived_messages.date DESC, derived_messages.id DESC LIMIT $limit $offset
I hope someone can help m on this.
Thank you.
It's possible but unlikely someone will write the query for you.
My recommendation on tackling such a query is to write each individual subquery as its own Zend_Db_Select object and then build the final query using the subqueries that you already have objects for.
Zend_Db_Select doesn't directly support the IF function, so for that you will need to use Zend_Db_Expr to add that statement into your select.
Here is a basic example of what I am talking about. Let's build the following query:
SELECT IF(msg.toId = 'drew010', msg.fromId, msg.toId), id, name, age, history.ip
FROM users
JOIN history ON users.id = history.userId
WHERE users.id = (
SELECT id FROM users WHERE loginCount > 1000
)
GROUP BY id,
ORDER BY age DESC
First build the subselect that select users where loginCount > 1000.
$subquery1 = $db->select()
->from('users', array('id'))
->where('loginCount > ?', 1000);
Next, build the outer query with the IF function:
$cols = array(
new Zend_Db_Expr('IF(' . $db->quoteInto('msg.toId = ?', 'drew010') . '), msg.fromId, msg.toId'),
'id', 'name', 'age'
);
$query = $db->select()
->from('users', $cols)
->join('history', 'users.id = history.userId', array('ip'))
->where('id = ?', $subquery1)
->group('id')
->order('age DESC');
echo $query;
The output:
SELECT
IF(msg.toId = 'drew010', msg.fromId, msg.toId),
`users`.`id`,
`users`.`name`,
`users`.`age`,
`history`.`ip`
FROM `users`
INNER JOIN `history`
ON users.id = history.userId
WHERE id = (
(SELECT `users`.`id`
FROM `users`
WHERE (loginCount > 1000))
)
GROUP BY `id`
ORDER BY `age` DESC
So the way to go is break the entire query into individual queries first, and then construct the outer query. Just have patience and take it slow. That and read over the Zend_Db_Select docs to get a full picture of what you have available to you.
$STH_1 = $DBH_R->query("SELECT table_name
FROM information_schema.tables
WHERE table_name
LIKE 'v_c_ei\_9%'
");
$stmts_1 = array();
while (($row_1 = $STH_1 -> fetch_assoc()) !== null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *
FROM $table_name
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
");
}
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= "\nORDER BY date_time ASC";
$STH_5_2 = $DBH_R->query($stmt_1);
while (($row_5_2 = $STH_5_2 -> fetch_assoc()) !== null){
OK, the script above is working ok. But, I want (must) change its functionality. I must do selection before UNION (something like ORDER BY ... LIMIT) but I know - this is not working. The solution is to change sprintif into UNION & UNION & UNION ... But the problem is - we don't know how much tables we have.
The table names from the first query looks like
v_c_ei_9001
v_c_ei_9002
..........
v_c_ei_9030
..........
ect.
Than the q: how change the sprintif (and maybe array $stmts_1 too) from abowe into the UNION in situation when we don't know how much tables we have?
thnks
When you add ORDER BY and LIMIT clauses to each constituent of the UNION, as follows:
while (($row_1 = $STH_1 -> fetch_assoc()) !== null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *
FROM $table_name
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
");
}
And then you do the following:
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= "\nORDER BY date_time ASC"; // <---- remember this bit
The resulting string in $stmt_1 will look something like this:
SELECT *
FROM v_c_ei_9001
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
UNION
...
UNION
SELECT *
FROM v_c_ei_9030
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
ORDER BY date_time ASC -- it's appearing down here!
As you can see, the final constituent of your UNION has two ORDER BY clauses, which is a syntax error. Either remove the line commented remember this bit above, or else (if you need to reorder the unified queries) you must make the UNION a subquery to an outer query that performs the reordering:
$stmt_1 = "SELECT * FROM ("
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= ") ORDER BY date_time ASC";
As I see, the simple way to show itself is write whatever, instead consider the solution of the problem. The situation is similar to evaluating questions - if the complexity of the problem is beyond the involvement of the viewer it is easier to evaluate them negatively than actually help the man who asks. And not just speak, instead of writing anything.
For all those who may face such a problem I give operating solution.
The simplest overall solution was to specify the tables on which the main query is executed. What was to be obtained in the main query by ORDER BY was obtained first auxiliary request on the first query by pre-rank the tables on the main query is executed.
In this way we avoid the problem 2x ORDER BY in the main query, because the ORDER BY clause is transferred to the first auxiliary request.
$STH_1 = $DBH_R->query("SELECT c.table_name
FROM v_c_country c
INNER JOIN information_schema.tables i ON i.table_name = c.table_name
ORDER BY c.country_name_pl ASC ");
while (($row_1 = $STH_1 -> fetch_assoc()) != null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *,'$table_name' AS table_name, time(date_time) AS time_dt, date(date_time) AS date_dt, MAX(date_time) AS MAXdate
FROM $table_name
WHERE ei_code = '1117' AND (DAY(date_time) != '00')
AND date_time = (SELECT MAX(date_time) FROM $table_name WHERE ei_code = '1117' AND index_released = '1')
");
}
$stmt_1 = implode("\nUNION\n", $stmts_1);
$STH_5_2 = $DBH_R->query($stmt_1);
Often I meet here with the tolerant approach to the questions asked, you know that if someone asks a question that awaits us - looking for - ask for help in solving the problem. I really, really thank all those who reach out a helping hand and give really helpful answer. These people really do happen.
select a.id, b.title, b.start_time, b.end_time from tv_channel a
left join tv_program b on a.id = b.tv_channel_id and b.start_time >= ‘2011-09-23 12:00:00′ and b.end_time <= '2011-09-23 14:30:00'
order by a.code
limit 0, 10;
–pager object
tnx
What's the question ? Do you want to write this SQL query in Propel ?
<?php
TvChannelQuery::create('a')
->joinTvProgram('b')
->addJoinCondition('b', 'b.StartTime >= 2011-09-23 12:00:00')
->addJoinCondition('b', 'b.EndTime >= 2011-09-23 14:30:00')
->orderByCode()
->limit(10)
;
Something like that should work but be be careful about values passed in addJoinCondition, there is no binding here and if you want to change these values you have to use it to prevent SQL injections or other security issues.
$c = new Criteria();
$c->addLeftJoin(tv_channel.id = tv_program .channel_id);
$c->add(tv_program.start_time, '2011-09-23 12:00:00', Criteria::GREATER_EQUAL);
$c->add(tv_program.end_time, '2011-09-23 14:30:00', Criteria::LESS_EQUAL);
$c->addAscendingOrderByColumn(tv_channel.code);
$c->setLimit(10);
$rs = DoSelect($c); //actual select execution here...