How do I do this sql query in Zend Framework, I need to some how do this in the PDO context I think? I tried ->query but not sure if I am getting this right. The three variables are user_id and to and from date.
SELECT
ss.subcategory_id,
ss.subcategory_name,
ss.subcategory_issaving,
IFNULL(SUM(m.mv_monthly_total),0) AS expendsum
FROM
(SELECT
s.subcategory_id,
s.subcategory_name,
s.subcategory_issaving
FROM
subcategory s
WHERE
s.subcategory_isexpend = 'Y'
AND
s.subcategory_issaving = 'Y') ss
LEFT JOIN
mv_monthly m
ON ss.subcategory_id = m.mv_monthly_subcategory_id
AND m.mv_monthly_user_id = 2
AND m.mv_monthly_month >= '2010-01-01'
AND m.mv_monthly_month <= '2020-01-01'
GROUP BY
ss.subcategory_id,
ss.subcategory_name,
ss.subcategory_issaving
ORDER BY
ss.subcategory_issaving DESC,
expendsum;
I have tried the following with no luck
$db = Zend_Db_Table::getDefaultAdapter();
$dbExpr1 = new Zend_Db_Expr("s.subcategory_id, s.subcategory_name, s.subcategory_issaving");
$dbExpr2 = new Zend_Db_Expr("ss.subcategory_id, ss.subcategory_name, ss.subcategory_issaving, IFNULL(SUM(m.mv_monthly_total),0) AS expendsum");
$select = $db->select()
->from(
array(
'ss' => new Zend_Db_Expr(
'('. $db->select()
->from(array("s" => "subcategory"), $dbExpr1)
->where("s.subcategory_isexpend = 'Y'")
->where("s.subcategory_issaving = 'Y'") .')'
)
),
$dbExpr2
)
->joinLeft(array("m" => "mv_monthly"), "ss.subcategory_id = m.mv_monthly_subcategory_id")
->where("m.mv_monthly_user_id = ?", $user_id)
->where("m.mv_monthly_month >= ?", $fromMonth)
->where("m.mv_monthly_month <= ?", $toMonth)
->group(array("ss.subcategory_id","ss.subcategory_name","ss.subcategory_issaving"))
->order(array("ss.subcategory_issaving DESC", "expendsum"));
$row = $db->fetchAll($select);
For such a complex query, you can just execute it directly rather than using the object oriented approach as it gets fairly complicated with a query like that.
Try something like this, replacing my query with yours, and binding your variables into the query:
$db = Zend_Db_Table::getDefaultAdapter();
$stmt = new Zend_Db_Statement_Pdo($db, 'SELECT a, b, c FROM a WHERE username = ? AND date = ?');
try {
$res = $stmt->execute(array($user_id, $fromMonth));
if ($res) {
$rows = $stmt->fetchAll();
}
} catch (Zend_Db_Statement_Exception $dbex) {
// log Query failed with exception $dbex->getMessage();
}
If you prefer to use the object oriented approach, or need to because some parts of the query will be conditional, I usually build by subqueries up first as their own select, and you can simply embed those in to the main query with the select object for the subquery.
Here is what I mean by that:
$subselect = $this->getDbTable()
->select()
->from('mytable', array('time' => 'max(time)', 'id'))
->where('id IN (?)', $serialNumbers)
->group('id');
$select = $this->getDbTable()
->select()
->setIntegrityCheck(false)
->from('mytable')
->join('other', 'mytable.id = other.id', array('label'))
->join(array('dt' => $subselect),
'(mytable.time, mytable.id) = (dt.time, dt.id)', '');
Related
I have problem to merge two conditions in my query
public function GetInbox($user_id , $line_number = false , $seeall = false , $limit = 0,$SearchWhere = null)
{
if(!$SearchWhere)
$SearchWhere = new Where();
if(!$seeall)
{
$UsersLineTable = new UsersLinesTable($this->adapter);
$UsersLine = $UsersLineTable->fetchAll(array('user_id = ?' => $user_id,'owner_type = ?' => '1'));
if(!$UsersLine) return false;
$SearchWhere2 = new Where();
foreach ($UsersLine as $key => $value) {
$SearchWhere2->equalTo("recipient_number",$value['line_number'])
->or
->equalTo("recipient_number",'98'.$value['line_number'])
->or;
}
$Select = new Select();
$Select->where($SearchWhere2);
$Select->where($SearchWhere);
if($limit)
$Select->limit($limit);
$Select->order("receive_date DESC");
$MessageProvidersInboxTable = new MessageProvidersInboxTable($this->adapter);
return $MessageProvidersInboxTable->fetchBySelect($Select);
}else{
$MessageProvidersInboxTable = new MessageProvidersInboxTable($this->adapter);
return $MessageProvidersInboxTable->fetchAll($SearchWhere);
}
}
$SearchWhere is a Where class,
$SearchWhere2 is second conditions
In this case
$Select->where($SearchWhere2);
$Select->where($SearchWhere);
$select just contain $SearchWhere conditions.
I want this query
Where condition1 AND (condition2)
is that important that condition2 contain conditions include OR operand.
Sincerely
Try this, it should work. Writing without looking at zend\db code:
$where = new \Zend\Db\Sql\Where;
$where->addPredicate($SearchWhere, $where::OP_AND);
$where->addPredicate($SearchWhere2, $where::OP_AND);
$select->where($where);
Basically, Where object is a subclass of Predicate. So it should work as any other predicate.
$condgrade = $DB->get_recordset_sql('SELECT c.fullname, gi.itemtype, gi.itemname,
gg.userid, gg.finalgrade FROM
'.$CFG->prefix.'grade_items gi
JOIN '.$CFG->prefix.'grade_grades gg ON gi.id =
gg.itemid JOIN '.$CFG->prefix.'course c ON c.id =
gi.courseid WHERE
gi.itemtype IN ("course") AND
gg.userid = '.$USER->id.'');
foreach($condgrade as $cgg)
{
$this->content->text .= html_writer::div($cgg->fullname.' : '.round($cgg->finalgrade).'%', array('class' => 'cours'));
}
Is there any other way of retrieving data directly from the query, rather using foreach loop everytime something like in mysql : mysql_fetch_object($users);
$records = $DB->get_records_sql('SELECT c.fullname, gi.itemtype, gi.itemname,
gg.userid, gg.finalgrade FROM
{grade_items} gi
JOIN {grade_grades} gg ON gi.id =
gg.itemid JOIN {course} c ON c.id =
gi.courseid WHERE
gi.itemtype IN ("course") AND
gg.userid = :userid', array('userid' => $USER->id));
This will return an array of records.
Note also, the use of {tablename} notation, rather than manually inserting the $CFG->prefix and the use of ':userid' bound parameter + parameter list passed as "array('userid' => $USER->id)", which helps to protect you from SQL injection attacks.
Get a single record?
$user = $DB->get_record('user', array('id' => 1));
http://docs.moodle.org/dev/Data_manipulation_API#Getting_a_single_record
EDIT : As well as the recommendations from davosmith, you also need to have a unique id in the first column. Also you can just use $DB->get_records_sql() - use $DB->get_recordset_sql() if you expect a large amount of data. If you do use get_recordset_sql() then you will also need to check the query is valid with $condgrade->valid() and close it after $condgrade->close();
$sql = "SELECT gg.id,
c.fullname,
gi.itemtype,
gi.itemname,
gg.userid,
gg.finalgrade
FROM {grade_items} gi
JOIN {grade_grades} gg ON gi.id = gg.itemid
JOIN {course} c ON c.id = gi.courseid
WHERE gi.itemtype = :itemtype
AND gg.userid = :userid";
$params = array('itemtype' => 'course', 'userid' => $USER->id);
$condgrade = $DB->get_records_sql($sql, $params);
This will return an array of record objects. The array key will be whatever is in the first column. eg:
$condgrade[1] = $recordobject;
So you can access a record object directly eg:
with $condgrade[1]->fullname
But you won't know what the id is unless you retrieve it from the database. So I'm not clear why you want to access the object directly? If you can give me an example of how you would use this directly then I can try to give an answer.
Select query in zend framework 2.2 with multiple where clause and order by desc.
My query is
Select 'vch_no' from vaucher_mst where 'series_sno'=12 and vchtype_sno=13 order by vch_no,desc
How can I perform this query? Here is my try:
public function getvchno() {
$select = new select();
$select->from($this->table);
$this->select('vch_no');
$where = new where();
$where->equalTo('series_sno',12);
$where->equalTo('vchtype_sno',13);
$select->where($where);
$order_by='vch_no';
$order=Select::ORDER_DESCENDING;
$select->order($order_by . ' ' . $order);
$limit=1;
$select->LIMIT(1);
$statement = $this->select($select);
print_r($statement);die;
if (!$row) {
throw new \Exception("Could not find row $id");
}
}
I do not know Zend 2 but according to the doc, this should work:
// Select 'vch_no' from vaucher_mst where 'series_sno'=12 and vchtype_sno=13 order by vch_no,desc
$select = new Select();
$select->from('vaucher_mst')
->columns(array('vch_no'))
->where(array('series_sno = 12', 'vchtype_sno = 13'))
->order('vch_no DESC');
Keep me informed :)
I have this SQL query:
SELECT pais FROM pais LEFT OUTER JOIN users_has_pais ON pais.id = users_has_pais.pais_id WHERE users_has_pais.users_id = 100
And I'm trying to write something similar within a model using the leftJoin method from Zend_Db_Table but I have no clue on what I'm doing.... I tried with something like this:
$resultSetPais = Zend_Db_Table::getDefaultAdapter();
$some = $resultSetPais->select()
->joinLeft( array ( 'users_has_pais' => 'users' ),
'pais.id = users_has_pais.pais_id', 'pais' );
But truth is I have no idea how to make it work and this code just returns the adapter information.
SOLVED:
$instance = Zend_Db_Table_Abstract::getDefaultAdapter();
$pais = $instance->select();
$pais->from(array('p' => 'pais'), array('p.pais') )
->join( 'users_has_pais', 'p.id = users_has_pais.pais_id' )
->where( 'users_has_pais.users_id = ?', $row->id );
$paisEntry = $instance->fetchCol($pais);
I'm adding the answer to the question as suggested by #Jaitsu. For this kind of left join:
SELECT pais FROM pais LEFT OUTER JOIN users_has_pais ON pais.id = users_has_pais.pais_id WHERE users_has_pais.users_id = 100
The code should be something like:
$instance = Zend_Db_Table_Abstract::getDefaultAdapter();
$pais = $instance->select();
$pais->from(array('p' => 'pais'), array('p.pais') )
->join( 'users_has_pais', 'p.id = users_has_pais.pais_id' )
->where( 'users_has_pais.users_id = ?', $row->id );
$paisEntry = $instance->fetchCol($pais);
hey this code produces an INNER JOIN sql query, not an OUTER JOIN - it is different thing, right? so, what should be the correct way of doing OUTER JOIN?
I'm having some problems translating this query to use ZF's Zend_Db_Select:
SELECT b.id, b.title, b.description
FROM memberships AS m
JOIN blogs AS b ON b.id = m.blog_id
WHERE m.user_id = ?
ORDER BY m.created
LIMIT 0, 30
(this query works and returns results)
Memberships is a link table between blogs and users. It's a simple | id | blog_id | user_id | affair.
Here's what I have so far:
// $table = Zend_Db_Table instance, $id = a user id
$select = $table->select()
->from(array('m' => 'memberships'), array('b.id', 'b.title', 'b.description'))
->join(array('b' => 'blogs'), 'b.id = m.blog_id')
->where('m.user_id = ?', (int) $id)
->order('m.created DESC')
->limit(0, 30);
This is the (strange (to me)) error I'm getting:
#0: Select query cannot join with another table
Occurred on line 211 of D:\...\library\Zend\Db\Table\Select.php.
Thanks for your help.
You could also still use the traditional $model->select() object by adding setIntegrityCheck(false), like so.
$select = $table->select()
->setIntegrityCheck(false)
->from(array('m' => 'memberships'), array('b.id', 'b.title', 'b.description'))
->join(array('b' => 'blogs'), 'b.id = m.blog_id')
->where('m.user_id = ?', (int) $id)
->order('m.created DESC')
->limit(0, 30);
This disables the check that is throwing the exception:
#0: Select query cannot join with another table
When retrieved from your table object, the statement will be limited to that table I think. The Zend_Db_Table::select() methods returns a Zend_Db_Table_Select object which is a subclass of Zend_Db_Select and imposes this restriction. Try this instead:
$db = Zend_Db::factory( ...options... );
$select = new Zend_Db_Select($adapter);
$select->from( 'my_table_name' )->join( ...
If you prefer, the following should be equivalent:
$db = Zend_Db::factory( ...options... );
$db->select()->from( 'my_table_name' )->join( ...