$this->db->insert_id() giving fatal error postgresql codeigniter - codeigniter

I am using Codeigniter 2.0.1 and Postgresql 8.1. My code uses transactions within try-catch blocks.
On a simple insert at times I get a "Fatal Error"
Fatal Error: Call to a member function row() on a non-object in
<...path...>/system/database/drivers/postgre/postgre_driver.php on
line 357
My Database Config is:
$db['default']['hostname'] = "localhost";
$db['default']['username'] = "***";
$db['default']['password'] = "***";
$db['default']['database'] = "***";
$db['default']['dbdriver'] = 'postgre';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = TRUE;
$db['default']['db_debug'] = FALSE;
$db['default']['cache_on'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['swap_pre'] = '';
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;
The lne of my Model code that is causing the error is "$id = $this->db->insert_id();".
I say so because the line that causes the error is within insert_id() method and it is being used only once in the model.
A code snapshot of the model is given below.
try {
// CODE TO FILL UP $data ARRAY
$this->DBquery("BEGIN");
$this->DBinsert('<TABLE NAME>', $data);
$id = $this->db->insert_id();
// SOME MORE CODE
}
catch(Exception $e) {
$this->DBquery("ROLLBACK");
//echo $e->getMessage();
return 0;
}
$this->DBquery("COMMIT");
return $id;
$this->DBquery and $this->DBinsert are custom methods made by me on a base model class which extends the CI_Model class. These methods function full well.
Below is the insert_id method in postgre_driver.php and line 357 is "$row = $query->row();"
function insert_id()
{
$v = $this->_version();
$v = $v['server'];
$table = func_num_args() > 0 ? func_get_arg(0) : NULL;
$column = func_num_args() > 1 ? func_get_arg(1) : NULL;
if ($table == NULL && $v >= '8.1')
{
$sql='SELECT LASTVAL() as ins_id';
}
elseif ($table != NULL && $column != NULL && $v >= '8.0')
{
$sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
$query = $this->query($sql);
$row = $query->row();
$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
}
elseif ($table != NULL)
{
// seq_name passed in table parameter
$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
}
else
{
return pg_last_oid($this->result_id);
}
$query = $this->query($sql);
$row = $query->row(); // LINE 357
return $row->ins_id;
}
Its so more confusing because the problem is not always. It happens sometimes but with a good enough frequency to hamper work. The system is being used by about 8-10 users and so I guess concurrency should not be an issue.
Also, I am using pconnect and number of connections is unlimited.

This sounds like maybe some of your insert statements are failing. If something errors out inside of a transaction like this, it can invalidate the transaction. If you look in the log file, you may find entries like "current transaction is aborted, commands ignored until end of transaction." (What's happening is the $query variable in the insert_id function doesn't receive a valid query result value, so calling functions on it fails at that point)
The best way to handle this is probably to modify your custom DBinsert function to return a value indicating the success or failure of the insert operation. (You should just be able to return the value of whatever insert command you're running internally)
Then, you can do something like this:
$insert_ret_val = $this->DBinsert('<TABLE NAME>', $data);
if($insert_ret_val){
//insert success!
$id = $this->db->insert_id();
}else{
//handle failed insert here, rollback, whatever
}

Related

model and controller query to merge timein and timeout with single row in codeigniter

Please teach me how can I achieve this(Codeigniter framework)
Please see images that I want to achieve thank you.
and I'm also new to codeigniter and want to understand the answer.
enter image description here
Here is my database:
enter image description here
model
public function get_attendance_employees() {
$sql = 'SELECT * FROM tbl_employee';
//$binds = array(1);
$query = $this->db->query($sql);
return $query;
}
public function attendance_first_in_check($userid,$attendance_date) {
$sql = "SELECT * FROM tbl_employee_time_log as time_log WHERE userid = ? and substring(time_log.time,1,10) = ? and type = 'timein' limit 1";
$binds = array($userid,$attendance_date);
$query = $this->db->query($sql,$binds);
return $query;
}
public function attendance_first_in($userid,$attendance_date) {
$sql = "SELECT * FROM tbl_employee_time_log as time_log WHERE userid = ? and substring(time_log.time,1,10) = ? and type = 'timein'";
$binds = array($userid,$attendance_date);
$query = $this->db->query($sql, $binds);
return $query->result();
}
public function attendance_first_out_check($userid,$attendance_date) {
$sql = "SELECT * FROM tbl_employee_time_log as time_log WHERE userid = ? and substring(time_log.time,1,10) = ? and type = 'timeout' order by id desc limit 1";
$binds = array($userid,$attendance_date);
$query = $this->db->query($sql, $binds);
return $query;
}
public function attendance_first_out($userid,$attendance_date) {
$sql = "SELECT * FROM tbl_employee_time_log as time_log WHERE userid = ? and substring(time_log.time,1,10) = ? and type = 'timeout' order by id desc limit 1";
$binds = array($userid,$attendance_date);
$query = $this->db->query($sql, $binds);
return $query->result();
}
controller
public function attendance_bio()
{
$session = $this->session->userdata('username');
if(!empty($session)){
$this->load->view("admin/timesheet/attendance_bio", $data);
} else {
redirect('admin/');
}
// Datatables Variables
$draw = intval($this->input->get("draw"));
$start = intval($this->input->get("start"));
$length = intval($this->input->get("length"));
$attendance_date2 = $this->input->get("attendance_date"); //string
//$ref_location_id = $this->input->get("location_id");
//$convert_atten = strtotime($attendance_date2); //int value
//$attendance_date = $convert_atten->format('m-d-Y');
$attendance_date = date("m-d-Y",strtotime($attendance_date2));
//$timein = $this->Bio_model->get_attendance_date();
//$timein = $this->Bio_model->get_attendance_timein($get_day);
//$timein = $this->Bio_model->get_all();
$employee = $this->Bio_model->get_attendance_employees();
$data = array();
//var_dump($attendance_date);
foreach($employee->result() as $r){
$check = $this->Bio_model->attendance_first_in_check($r->userid,$attendance_date);
if($check->num_rows() > 0){
// check clock in time
$first_in = $this->Bio_model->attendance_first_in($r->userid,$attendance_date);
//$first_in2 = $first_in[0]->time->format('m-d-Y');
// clock in
$clock_in = new DateTime(strtotime($first_in[0]->time));
//$clock_in2 = $clock_in->format('H:i');
$clock_in2 = date_format($clock_in->time, 'H:i');
//$clock_in2 = var_dump($clock_in);
} else {
$clock_in2 = '-';
$clock_in = '-';
}
$check_out = $this->Bio_model->attendance_first_out_check($r->userid,$attendance_date);
if($check_out->num_rows() == 1){
$first_out = $this->Bio_model->attendance_first_out($r->userid,$attendance_date);
//$first_out2 = $firs
$clock_out = new DateTime(strtotime($first_out[0]->time));
if ($first_out[0]->time!='') {
//$clock_out2 = $clock_out->format('H:i');
//$clock_out2 = date('H:i',$clock_out);
$clock_out2 = date_format($clock_out->time, 'H:i');
} else {
$clock_out2 = '-';
}
}else {
$clock_out2 = '-';
$clock_out = '-';
}
$data[] = array(
$r->userid,
$attendance_date,
$clock_in2,
$clock_out2,
);
}
$output = array(
"draw" => $draw,
"recordsTotal" => $employee->num_rows(),
"recordsFiltered" => $employee->num_rows(),
"data" => $data
);
echo json_encode($output);
exit();
}
Thank you for providing more information on the topic and the code you have attempted so far. I have supplied an algorithm which I believe will work for you.
Contoller:
<?php namespace App\Controllers;
use App\Models\EmployeeTimeLog;
class Home extends BaseController
{
public function index($employeeId)
{
// get all between dates
$emplyeeModel = new EmployeeTimeLog();
// get one week before today - for example
$startDate = date("Y-m-d", strtotime("-1 week"));
$endDate = date("Y-m-d");
// get clock-in and clock-out for employee between dates
$timeIn = $emplyeeModel->getTimeIn($employeeId, $startDate, $endDate)->getResult();
$timeOut = $emplyeeModel->getTimeOut($employeeId, $startDate, $endDate)->getResult();
$timeInIndex = 0;
$timeOutIndex = 0;
$output = [];
$nextDate = $startDate;
// loop through all the days between start and end date
while($nextDate < $endDate){
// get the lowest "timein" datetime which is the same date as the search date $nextDate
$nextTimeIn = NULL;
while($timeInIndex < count($timeIn) && date("Y-m-d", strtotime($timeIn[$timeInIndex]->Time)) == $nextDate){
if(is_null($nextTimeIn)){
$nextTimeIn = $timeIn[$timeInIndex];
}
$timeInIndex ++;
}
// get the highest "timeout" datetime which is the same day as the search date $nextDate
$nextTimeOut = NULL;
while($timeOutIndex < count($timeOut) && date("Y-m-d", strtotime($timeOut[$timeOutIndex]->Time)) == $nextDate){
$nextTimeOut = $timeOut[$timeOutIndex];
$timeOutIndex ++;
}
// enter into a 2 dimentional array with
// index 0 = timein
// index 1 = timeout
$output[] = [$nextTimeIn, $nextTimeOut];
// get the next date
$nextDate = date('Y-m-d', strtotime($nextDate. ' + 1 days'));
}
// return view with data
return view('welcome_message', ["output" => $output]);
}
}
Model:
<?php
namespace App\Models;
use CodeIgniter\Model;
class EmployeeTimeLog extends Model{
private $tableName = "tbl_employee_time_log";
public function __construct(){
$db = \Config\Database::connect();
$this->builder = $db->table($this->tableName);
}
private function timeData($employeeId, $startDate, $endDate){
// builder function DRY
$this->builder->where("EmployeeId", $employeeId);
$this->builder->where("Time >", $startDate);
$this->builder->where("Time <", $endDate);
$this->builder->orderBy("Time", "ASC");
}
public function getTimeIn($employeeId, $startDate, $endDate){
// call builder function and add timeIn to only get clock in times
$this->timeData($employeeId, $startDate, $endDate);
$this->builder->where("Type", "timein");
return $this->builder->get();
}
public function getTimeOut($employeeId, $startDate, $endDate){
// call builder function and add timeout to only get clock out times
$this->timeData($employeeId, $startDate, $endDate);
$this->builder->where("Type", "timeout");
return $this->builder->get();
}
}
?>
View:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Timesheets</title>
</head>
<body>
<h1>Timesheets</h1>
<?php
echo "<h1>Times</h1>";
foreach ($output as $times) {
echo "Time in: ";
if(!is_null($times[0])){
echo $times[0]->Time;
}else{
echo "-";
}
echo " Time out: ";
if(!is_null($times[1])){
echo $times[1]->Time;
}else{
echo "-";
}
echo "<br>";
}
?>
</body>
</html>
Output:
Database:
The whole algorithm works by searching through the date between the start and end date of the dates provided. You can then check any timein and timeout values which have the same date as the loop date. If a date cannot be found, the default is NULL which is replaced by "-" in the view.
The algorithm specifically gets the earliest timein and the latest timeout value for the employee. This means that if the employee clocks-in twice in one day the earliest date will be used and the opposite for clock-out.
This algorithm specifically works for one employee, but just use your select * employees and loop through instead of the employeeId on the controller. You may want to look in the documentation for the Query Builder in CodeIgniter it makes querying the database much easier, and will escape data to protect from SQL Injections etc.
It could be better to redesign your database table and check on insert rather than manipulate on select. Where you have one row for each day and the timein and timeout which represent the time. Something like this:
You can check to see if the date already exists, if so override the current value if needed. If the current date doesn't exist for that employee create a new record.
If you need any clarification, let me know,
Thanks,

Laravel 5.3 database transaction issue?

I have used more time with Laravel 5.0 on database transaction but when I change to Laravel 5.3.* it not work as I want even I have disabled commit() method all data still continue insert into database.
if ($request->isMethod('post')) {
DB::beginTransaction();
$cats = new Cat();
$cats->parent_id = $this->request->input('category_id');
$cats->status = ($this->request->input('status')) ? $this->request->input('status') : 0;
if ($res['cat'] = $cats->save()) {
$catD = new CategoryDescriptions();
$catD->category_id = $cats->id;
$catD->language_id = 1;
$catD->name = $this->request->input('en_name');
if ($res['cat2'] = $catD->save()) {
$catD2 = new CategoryDescriptions();
$catD2->category_id = $cats->id;
$catD2->language_id = 2;
$catD2->name = $this->request->input('kh_name');
$res['all'] = $catD2->save();
}
}
if ($res) {
//DB::commit();
return $res;
}
return [false];
}
Check this line ($res['cat'] is a boolean):
if($res['cat'] = $cats->save()) {
And this ($res is an array. You compare an array as boolean!):
if($res){
The right condition should be:
$res = array(); // the first line of your method
// .... your http method check, start transaction, etc.
if (!in_array(false, $res, true)) { // check if array doesn't contain 'false values'
DB::commit();
}

Magento : Original Price is Zero in Sales Order View from programatic order

I am generating orders from a custom web service called from a mobile app. However when the order is finally generated, I get "Original Price" as Rs0.00 . This is creating a problem since we have third party integrations for invoicing and Shipping.
However in the normal course of action when order is generated from website, the Original Price is correct.
I inspected the sales_flat_order_item table for both these orders, the original_price is indeed 0.00 in the first order, Hence I must be missing something in my code which is not setting the original_price for the orderItem.
Here is the code where the quote is converted to order.
public function placeorder($custid, $Jproduct, $store, $address, $couponCode, $is_create_quote, $transid, $payment_code, $shipping_code, $currency, $message)
{
$res = array();
$quantity_error = array();
try {
$quote_data = $this->prepareQuote($custid, $Jproduct, $store, $address, $shipping_code, $couponCode, $currency, 1, 0);
if ($quote_data["status"] == "error") {
return $quote_data;
}
$quote = Mage::getModel('sales/quote')->load($quote_data['quote_id']);
$quote = $this->setQuoteGiftMessage($quote, $message, $custid);
$quote = $this->setQuotePayment($quote, $payment_code, $transid);
$convertQuote = Mage::getSingleton('sales/convert_quote');
try {
$order = $convertQuote->addressToOrder($quote->getShippingAddress());
}
catch (Exception $Exc) {
echo $Exc->getMessage();
}
$items = $quote->getAllItems();
foreach ($items as $item) {
$orderItem = $convertQuote->itemToOrderItem($item);
$order->addItem($orderItem);
}
try {
$decode_address = json_decode(base64_decode($address));
$order->setCustomer_email($decode_address->billing->email);
$order->setCustomerFirstname($decode_address->billing->firstname)->setCustomerLastname($decode_address->billing->lastname);
}
catch (Exception $e) {
}
$order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
$order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
$order->setPayment($convertQuote->paymentToOrderPayment($quote->getPayment()));
$order->save();
$quantity_error = $this->updateQuantityAfterOrder($Jproduct);
$res["status"] = 1;
$res["id"] = $order->getId();
$res["orderid"] = $order->getIncrementId();
$res["transid"] = $order->getPayment()->getTransactionId();
$res["shipping_method"] = $shipping_code;
$res["payment_method"] = $payment_code;
$res["quantity_error"] = $quantity_error;
$order->addStatusHistoryComment("Order was placed using Mobile App")->setIsVisibleOnFront(false)->setIsCustomerNotified(false);
if ($res["orderid"] > 0 && ($payment_code == "cashondelivery" || $payment_code == "banktransfer" || $payment_code == "free")) {
$this->ws_sendorderemail($res["orderid"]);
$order->setState(Mage_Sales_Model_Order::STATE_NEW, true)->save();
$res["order_status"] = "PENDING_PAYMENT";
} else {
$order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, true)->save();
$res["order_status"] = "PENDING_PAYMENT";
}
}catch (Exception $except) {
$res["status"] = 0;
$res["shipping_method"] = $shipping_code;
$res["payment_method"] = $payment_code;
}
return $res;
}
It would be very helpful if someone points out what I missed. I will edit if any other info is required.
Missing original_price indicates that you didn't run collectTotals() on the quote yet, try the following:
$quote->collectTotals()->save();
$order->save();

Create category programmatically in multiple languages in Magento

i am tyring to add categories programmatically for german and english languages.
website-ID: 1
website store-ID: 1
view-ID english, code "en" => 1
view-ID german, code "de" => 2
$category['general']['path'] = $v['cat_name_de'];
$category['general']['name'] = $v['cat_name_de'];
$category['general']['meta_title'] = "";
$category['general']['meta_description'] = "";
$category['general']['is_active'] = 1;
$category['general']['url_key'] = urlencode($v['cat_name_de']);
$category['general']['display_mode'] = "PRODUCTS";
$category['general']['is_anchor'] = 0;
$category['category']['parent'] = $v['magento_cat_id'];
$storeId = 0; // default
$magento_subcat_id = createCategory($category, $storeId);
...
function createCategory($data, $storeId) {
echo "Erzeuge '{$data['general']['name']}' - Elternkategorie:
[{$data['category']['parent']}] ...";
$category = Mage::getModel('catalog/category');
$category->setStoreId($storeId);
if (is_array($data)) {
$category->addData($data['general']);
if (!$category->getId()) {
$parentId = $data['category']['parent'];
if (!$parentId) {
if ($storeId) {
$parentId = Mage::app()->getStore($storeId)->getRootCategoryId();
} else {
$parentId = Mage_Catalog_Model_Category::TREE_ROOT_ID;
}
}
$parentCategory = Mage::getModel('catalog/category')->load($parentId);
$category->setPath($parentCategory->getPath());
}
if ($useDefaults = $data['use_default']) {
foreach ($useDefaults as $attributeCode) {
$category->setData($attributeCode, null);
}
}
$category->setAttributeSetId($category->getDefaultAttributeSetId());
if (isset($data['category_products']) &&
!$category->getProductsReadonly()) {
$products = array();
parse_str($data['category_products'], $products);
$category->setPostedProducts($products);
}
try {
$category->save();
return $category->getId();
} catch (Exception $e) {
return FALSE;
}
}
}
What i am puzzling with at the moment is setting view-ID individually for passing the $category['general']['name'] for each language.
I tried to set each language string with a foreach setting english/german texts. But this did not work out, because i somehow mixed up setting the view correctly.
To make it short:
Creating categories and subcategories like this does work very good, but i do not get it to work to pass english/german categoty titles.
Thanks guys
For all of you who are struggeling with this situation i made a workaound like this:
I added all those values to the affected database tables directly. This is for sure a quick and dirty way, but it does the job.
For all in need of some ideas here is the (undocumented) snipped belonging to my initial post.
// Get values for next language insert
$entity_type_id = $category
->getResource()
->getTypeId();
$entity_id = $category->getEntityId();
$read_entity = Mage::getSingleton('core/resource')
->getConnection('core_write');
$sql_entity = "SELECT * FROM eav_attribute WHERE
`attribute_code` = 'name' AND
`entity_type_id` = " . $entity_type_id . ";";
$row_entity = $read_entity
->fetchRow($sql_entity);
$attribute_id = $row_entity['attribute_id'];
// prepare value for name field in different langauge
$val = Mage::getSingleton('core/resource')
->getConnection('default_write')
->quote($v['en']);
$sql_insert = "INSERT INTO `catalog_category_entity_varchar`
(`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`)
VALUES ($entity_type_id,$attribute_id,$storeId,$entity_id,$val);";
$read_entity->query($sql_insert);
I hope this helps someone out who is in need of this.

CI pagination double query

I am working in CI Framework. For pagination i use two queries, one for required output using limit, and another to count total number of rows. Is there any other way like both can be done from single query?
My query is:
{
$searchtxt = $this->input->post('searchtxt');
$datefrom = $this->input->post('fromdate');
$todate = $this->input->post('todate');
$status= $this->input->post('order_status');
$sc_id = $this->input->post('sc_id');
if($sc_id){
$this->db->where('('.'o.requested_sc_id = '.$sc_id.' OR o.requesting_sc_id = '.$sc_id.')');
//$this->db->where('o.requesting_sc_id =',$sc_id);
}
if ($status){
$this->db->where('o.order_status =',$status);
}
if ($status != '' && $status == 0 ){
$this->db->where('o.order_status = 0');
}
if($searchtxt){
$this->db->like('o.order_number',$searchtxt);
}
if($datefrom)
{
$this->db->where('o.order_dt >=', date("Y-m-d",date_to_timestamp($datefrom)));
}
if($todate)
{
$this->db->where('o.order_dt <=', date("Y-m-d",date_to_timestamp($todate)));
}
if ($this->session->userdata('usergroup_id')!=1 && $this->session->userdata('usergroup_id')!= 2 && $this->session->userdata('usergroup_id')!=6 ){
$this->db->where('('.'o.requested_sc_id = '.$this->session->userdata('sc_id').' OR o.requesting_sc_id = '.$this->session->userdata('sc_id').')');
//$this->db->where('o.requesting_sc_id = '.$this->session->userdata('sc_id'));
}
$this->db->select('o.order_id,o.order_number,o.order_dt,o.call_id,c.call_uid,o.order_status,o.order_dt,sc.sc_name,e.engineer_name');
$this->db->from($this->table_name.' AS o');
$this->db->join($this->mdl_callcenter->table_name.' AS c','c.call_id=o.call_id','left');
$this->db->join($this->mdl_servicecenters->table_name.' AS sc' ,'sc.sc_id=o.requested_sc_id','left');
$this->db->join($this->mdl_engineers->table_name.' AS e', 'e.engineer_id = o.engineer_id','left');
$this->db->order_by('o.order_status ASC,o.order_dt DESC,o.order_created_ts DESC');
if(isset($page['limit'])){
$this->db->limit((int)$page['limit'],(int)$page['start']);
}
$result = $this->db->get();
//echo $this->db->last_query();
if ($status){
$this->db->where('o.order_status =',$status);
}
if ($status != '' && $status == 0 ){
$this->db->where('o.order_status = 0');
}
if($sc_id){
$this->db->where('o.requesting_sc_id =',$sc_id);
}
if($searchtxt){
$this->db->like('o.order_number',$searchtxt);
}
if($datefrom)
{
$this->db->where('o.order_dt >=', date("Y-m-d",date_to_timestamp($datefrom)));
}
if($todate)
{
$this->db->where('o.order_dt <=', date("Y-m-d",date_to_timestamp($todate)));
}
//if ($this->session->userdata('global_admin')!=1){
if ($this->session->userdata('usergroup_id')!=1 && $this->session->userdata('usergroup_id')!= 2 && $this->session->userdata('usergroup_id')!=6 ){
$this->db->where('o.requested_sc_id = '.$this->session->userdata('sc_id').' or o.requesting_sc_id = '.$this->session->userdata('sc_id'));
}
$this->db->select('o.order_id');
$this->db->from($this->table_name.' AS o');
$this->db->join($this->mdl_callcenter->table_name.' AS c','c.call_id=o.call_id','left');
$this->db->join($this->mdl_servicecenters->table_name.' AS sc' ,'sc.sc_id=o.requested_sc_id','left');
$this->db->join($this->mdl_engineers->table_name.' AS e', 'e.engineer_id = o.engineer_id','left');
$result_total = $this->db->get();
$orders['list'] = $result->result();
$orders['total'] = $result_total->num_rows();
return $orders;
}
Here is some explanation for this.
function($limit,$offset){
$this->db
->select("SQL_CALC_FOUND_ROWS emp", FALSE)
->select("*")
->from('tbl1')
->limit($limit, $offset);
$data["query_result"] = $this->db->get()->result_array();
$query = $this->db->query('SELECT FOUND_ROWS() AS `Count`');
$data["total_rows"] = $query->row()->Count;
return $data;
}
Here you see you are forced to get total count using another query.
Of course this is not what you want but it is impossible with single query using mysql.
But here is a php way.
function($limit,$offset){
$this->db
->select("*")
->from('tbl1');
$data["query_result"] = $this->db->get()->result_array();
$data["total_rows"] = array_slice($data["query_result"], $offset, $limit);
return $data;
}
This can be achieved with single query but involves php to get the desired result.

Resources