I have two tables, User and Company. I have joining them like this:
$table = $this->getDbTable();
$select = $table->select();
$select->setIntegrityCheck( false );
$select->from( array('User'), array( 'id' => 'id',
'name' => 'User.name',
'gender' => 'User.gender',
'Company_id' => 'User.Company_id'
));
$select->join( 'Company', 'Company.id = User.Company_id',
array( 'Company_name' => 'Company.name' ,
'Company_address' => 'Company.address'
));
$rows = $table->fetchAll( $select );
It is working and giving me accurate result. Problem is that I have to mentions column names in above codes. I want to get all columns without mentioning them in above piece of code.
For example I want something like this that get all columns(But it is not providing all column values):
$table = $this->getDbTable();
$select = $table->select();
$select->setIntegrityCheck( false );
$select->from( array('User') );
$select->join( 'Company', 'Company.id = User.Company_id' );
$rows = $table->fetchAll( $select );
Thanks
Leaving away the second parameter to the from call should work: http://framework.zend.com/manual/en/zend.db.select.html#zend.db.select.building.columns
Related
Is it possible to get distinct values and be case insensitive? I found a couple people saying to use the aggregate function but I would keep getting errors like: exception: field path references must be prefixed with a '$' ('Classification'.
public function getDistinctValues($cid, $table, $column)
{
$mongo = new MongoClient();
$db = $mongo->leadworks;
$collection = new MongoCollection($db, $table);
//$result = $collection->distinct($column);
$result = $collection->aggregate(array(
array(
'$unwind' => $column,
),
array(
'$group' => array(
'_id' => array(
'$toLower' => array(
$column,
),
),
),
),
));
return $result;
}
This is how my document looks:
{
_id:2065565,
Date:new Date(1411732940000),
Email:"email#email.com",
Other - Industry:null,
Other - Job Duties:null,
First Name:"Test Name",
Last Name:"Test Last Name",
Title:"engineer",
Company:"Company Name Here",
Country:"UNITED STATES",
State:"MI",
Zipcode:"48071-1514",
Phone number:"777-777-7777",
Company type:"Systems integration",
}
I'm specifically trying to get distinct values for Company and ignore case.
I have a find method that uses a DISTINCT clause to get results from my Model. The Controller code looks like below
$options = array(
'limit' => 10,
'fields' => array(
'DISTINCT id', 'title',
),
'contain' => array(
'Dealer' => array('id'),
),
'paramType' => 'querystring'
);
$this->Paginator->settings = $options;
$cars = $this->Paginator->paginate('Car'); // returns 6 distinct rows
The above query return 6 distinct rows and 12 total rows. So when I am displaying, the screen shows 6 distinct rows
However in the View, when I use
echo $this->Paginator->param('count'); // returns 12
I get a count of 12
I checked the SQL Log and noticed that the count query is not using the distinct clause. Any idea how I can override the Paginator count query to use the DISTINCT clause?
Found the solution,
In controller add distinct as an array parameter with other pagination options. So if I was trying to retrieve a list of Cars in my inventory with 10 cars at a time, the options would have a DISTINCT clause in the fields parameter and a separate parameter called distinct would also be added as shown below
$options = array(
'conditions' => $conditions,
'joins' => $joins,
'limit' => 10,
'fields' => array(
'DISTINCT Car.id', 'title', 'user_id'),
'contain' => array(
'Dealer' => array('id'),
),
'paramType' => 'querystring',
'distinct' => 'Car.id'
);
$this->Paginator->settings = $options;
$cars = $this->Paginator->paginate('Car');
In Model, use the below function to override the original paginateCount method
public function paginateCount($conditions = null, $recursive = 0, $extra = array()) {
$parameters = compact('conditions', 'recursive');
if (isset($extra['distinct'])) {
$parameters['fields'] = 'DISTINCT ' . $extra['distinct'];
$count = $this->find('count', array_merge($parameters, $extra));
} else {
// regular pagination
$count = $this->find('count', array_merge($parameters, $extra));
}
return $count;
}
No change in View
Cakephp 2.6
I have a Model, Temps, which has many tickets. In the index view of Temps I want to return for each record, the ticket with the date closest to the current date.
In mySQL it can be done as
'SELECT expiry_date FROM uploads WHERE expiry_date > CURDATE() ORDER BY expiry_date ASC LIMIT 1'
But I don't know how to run this as a sub query. My Current query to generate my results is as follows: (bearing in mind this has been configured for datatables) Tickets is an alias for the Upload Model
public function getAjaxIndexData($data) {
$tokens = explode(" ", $data['searchString']);
$conditions = array(
$this->alias . '.deleted' => false,
'OR' => array(
'CONCAT(' . $this->alias . '.first_name," ",' . $this->alias . '.last_name) LIKE' => '%' . implode(' ', $tokens) . '%',
),
$data['columnsFilter']
);
$fields = array(
'id',
'full_name',
'pps_number',
'mobile',
'email',
'start_date',
'time_served'
);
$order = array(
$data['orderField'] => $data['order']
);
$contain = array(
'LocalOffice.name',
);
$options = array(
'conditions' => $conditions,
'fields' => $fields,
'order' => $order,
'contain' => $contain,
'limit' => $data['limit'],
'offset' => $data['start']
);
$optionsNoFields = array(
'conditions' => $conditions,
'contain' => $contain,
);
$result['draw'] = $data['draw'];
$result['recordsTotal'] = $recordTotal = $this->find('count');
$result['recordsFiltered'] = $this->find('count', $optionsNoFields);
$result['data'] = $this->find('all', $options); //standard search
$result['data'] = $this->formatTable($result['data']);
return json_encode($result);
}
Within this query I would like to add a field that shows the nearest expiry date for each Temp.
How would I construct this?
Dynamically create a virtual field:
$this->virtualFields['nearest'] = '(SELECT expiry_date FROM uploads WHERE expiry_date > CURDATE() AND uploads.owner_id = '.$this->alias.'.ticket_id ORDER BY expiry_date ASC LIMIT 1')';
Then adjust your fields array
$fields = array(
'id',
'full_name',
'pps_number',
'mobile',
'email',
'start_date',
'time_served',
'nearest'
);
Also, the query could be rewritten as ("temp" needs to be replaced with the model alias)
SELECT MIN(expiry_date)
FROM uploads
WHERE expiry_date > CURDATE()
AND uploads.owner_id = temp.ticket_id;
Which means that a potentially better performing query would be to move that subquery out of the columns of the SELECT statement to a JOIN. For example:
SELECT *
FROM temp
LEFT JOIN (SELECT MIN(expiry_date) AS expiry,owner_id
FROM uploads
WHERE expiry_date > CURDATE())
GROUP BY owner_id) AS next_dates
ON next_dates.owner_id = temp.ticket_id;
There is join, and I need to include value from it in 'where'. Is there any way to do this? In other words, I want to apply 'where' clause only to that values, which being joined. I'm really got confused with it, and may be this task can be solved more easily.
$this->table = "CoolTable";
$sql = new Sql($this->getAdapter());
$select = $sql->select()
->columns(array(/*some expressions...*/))
->from($this->table)
->join(
array('ct' => 'CoolTable'),
new Expression('
ct.a = CoolTable.a AND
ct.b = CoolTable.b
'),
array()
)
/*another joins...*/
->where(array(
'CoolTable.a' => $someExternalVar,
'CoolTable.b = ?' => '$ct.a',
))
What about my tries:
'CoolTable.b = ?' => '$ct.a'
'CoolTable.b' => 'ct.a'
'CoolTable.b' => new Expression('ct.a') /*it's a really pity, yes*/
new Predicate\PredicateSet(
array(
new Operator(
'CoolTable.b',
Operator::OPERATOR_EQUAL_TO,
'ct.a'
),
),
Predicate\PredicateSet::TYPE_VALUE
),
Learning php and I am losing my mind trying to solve this for days now. Please help.
This is a code which goes thought a table COUPON, take data with a condition met, and download it afterwards. In this table COUPON I have USER_ID as number but I want to have a user name also, which is kept in another table USER.
How can I go to another table (USER) and take names (REALNAME) by this USER_ID which is the same in both tables?
if ( $_POST ) {
$team_id = abs(intval($_POST['team_id']));
$consume = $_POST['consume'];
if (!$team_id || !$consume) die('-ERR ERR_NO_DATA');
$condition = array(
'team_id' => $team_id,
'consume' => $consume,
);
$coupons = DB::LimitQuery('coupon', array(
'condition' => $condition,
));
if (!$coupons) die('-ERR ERR_NO_DATA');
$team = Table::Fetch('team', $team_id);
$name = 'coupon_'.date('Ymd');
$kn = array(
'id' => 'ID',
'secret' => 'Password',
'date' => 'Valid',
'consume' => 'Status',
);
$consume = array(
'Y' => 'Used',
'N' => 'Unused',
);
$ecoupons = array();
foreach( $coupons AS $one ) {
$one['id'] = "#{$one['id']}";
$one['consume'] = $consume[$one['consume']];
$one['date'] = date('Y-m-d', $one['expire_time']);
$ecoupons[] = $one;
}
down_xls($ecoupons, $kn, $name);
After this, I want to try to do the same thing using only SQL queries.
You would need to JOIN the tables in the SQL query
SELECT something FROM coupons as coupons JOIN user as user ON coupons.id=user.id
You should use join when you want to retrieve details from two tables.
Join table COUPON and table USER based on user_id . This should yield results you want.