MySQL Query - produce array within result - php

I would like to, in one query select orders and have their items attached to them (right now I'm selecting the orders, then using a separate query selecting the order_items - this is proving very slow on a large amount of orders...
orders: id | name | total
order_items: id | order_id | price | qty
order_items_info: id | order_id | order_item_id | tracking_no
The last thing I want to do is: add my order_items_info table to the item array.
$orders = array(
array(
'id' => '',
'name' => '',
'items' => array(
array(
'order_item_id' => '',
'price' => '',
'qty' => '',
'item_info' => array()
),
array(
'order_item_id' => '',
'price' => '',
'qty' => '',
'item_info' => array()
),
...
)
)
);

SELECT o.id,name,total,item_info,price,qty FROM orders o
JOIN order_items oi ON o.id=oi.order_id
JOIN order_items_info oii ON oii.order_id=o.id
AND oii.order_item_id=oi.id
Just a wild guess until you post your table info.

select * from orders join order_items on (orders.id = order_id)

Related

How can i select records from two tables in cake php(cake 2)

I am new to cake php . i have two tables
ce_landing
ce_stat
structure is
ce_stat
id keyword click
1 keyword1 24
2 keyword2 2
3 keyword3 6
ce_landing
id page_keyword
1 keyword1,check,keyword3
2 keyword2,usa,alphanumeric
i want to fetch all the records ce_landing.page_keyword is present in ce_stat.keyword. I am using this in my cake php model
public $hasMany = array(
'Stat' => array(
'className' => 'Stat',
'foreignKey' => 'keywor',
'dependent' => false,
'conditions' => array('Stat.keyword LIKE' => '%Landing.page_keywords%'),
'group' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
but this is generated sql query like
SQL Query: SELECT Stat.id, Stat.customer_id, Stat.account,
Stat.campaign_id, Stat.campaign, Stat.keyword,
Stat.ad_grp_id, Stat.ad_grp, Stat.impressions,
Stat.clicks, Stat.cost, Stat.qualityScore,
Stat.keywordState, Stat.date_from, Stat.date_to,
Stat.user_id, Stat.created, Stat.modified, Stat.keywor
FROM EB_adwords.ce_stats AS Stat WHERE Stat.keyword LIKE
'%Landing.page_keywords%' AND Stat.keyword =
('559f479a-82ac-4e3d-8c24-19b5c0a8011f')
so it returns null data because of AND Stat.keyword =('559f479a-82ac-4e3d-8c24-19b5c0a8011f') conditions.
Update
what i want to get all the records from ce_landing with total clicks according to keywords present . i.e for record 1 in ce_landing. i'll get the result
id page_keyword clicks
1 keyword1,check,keyword3 30
2 keyword2,usa,alphanumeric 2
You needs a SQL statement equivalent to:
SELECT ce_landing.id, ce_landing.page_keyword, SUM(ce_stat.click) AS total_clicks
FROM ce_landing
LEFT JOIN ce_stat
ON FIND_IN_SET(keyword,page_keyword)>0
GROUP BY ce_landing.id, ce_landing.page_keyword;
which does not easily translate to Cakephp's find method. Just use the query method to implement.
$this->Landing->query("SELECT Landing.id, Landing.page_keyword, SUM(ce_stat.click) AS total_clicks
FROM ce_landing AS Landing
LEFT JOIN ce_stat
ON FIND_IN_SET(keyword,page_keyword)>0
GROUP BY Landing.id, Landing.page_keyword;");

CakePHP retrieve data from another Model

I am new to cakephp and I have a little problem about retrieving data from another model.
My table association is like this:
Items hasMany Stocks
Stocks belongsTo Items
Items belongsTo UnitMeasurement
UnitMeasurement hasMany Items
My problem is I want to show UnitMeasurement Name to Stocks index html table view.
Current Html table view:
----------------------------------------------------------------------
Item | Stock Balance| Unit | Created |
----------------------------------------------------------------------
Microprocessor | 12 | DISPLAY UNIT NAME HERE!| 19/1/2014 |
Microcontroller| 20 | DISPLAY UNIT NAME HERE!| 19/1/2014 |
CPU | 12 | DISPLAY UNIT NAME HERE!| 19/1/2014 |
----------------------------------------------------------------------
How do I make the succesful query ?
Thanks.
EDIT:
This is my find query in my StocksController index function:
public function index() {
$this->Stock->recursive = 0;
$order = "Stock.id DESC";
//set orderby
$stock = $this->Stock->find('all',array('order'=>$order));
$this->set('stocks', $stock);
//query to find UnitMeasurement Name for Stocks Item
foreach ($stock as $stocks) {
//debug($stocks);
$this->loadModel('Items');
$unitMeasurement = $this->Items->find('first',array('fields'=>'unit_measurement_id','conditions'=>array('Items.id'=>$stocks['Stock']['item_id'])));
$this->set('units',$unitMeasurement);
}
}
Thanks again.
check this model name always singular please check and let me know if it works !
foreach ($stock as $stocks) {
//debug($stocks);
//$this->loadModel('Items');
$this->loadModel('Item');
$unitMeasurement = $this->Item->find('first',array('fields'=>'unit_measurement_id','conditions'=>array('Item.id'=>$stocks['Stock']['item_id'])));
$this->set('units',$unitMeasurement);
}
You could make a query like this:
$items = $this->Item->find('all', array(
'fields' => array(
'Item.name',
'SUM(Stock.amount) as amount',
'UnitMeasurement.name',
'Item.created',
),
'joins' => array(
array(
'table' => "stocks",
'alias' => "Stock",
'conditions' => "Item.id = Stock.item_id"
),
array(
'table' => 'unit_measurements',
'alias' => 'UnitMeasurement',
'conditions' => 'UnitMeasurement.id = Item.unit_measurement_id',
),
),
'group' => array('Item.id', 'Item.unit_measurement_id'),
));

How to display the field of other table?

I've 3 tables
The "Setup" table's schema is as follow.
id | name
1 | aaa
2 | bbb
Request table as follow
id| request_no| request_type_id (id of setup table)
1 | SM000001 | 1
2 | SM000002 | 2
this is history table
id | request_id | status | date
1 | 1 | Pending | 2013-07-04 14:39:03
2 | 1 | Reviewing | 2013-07-05 01:10:14
3 | 1 | Implementing | 2013-07-06 11:25:54
4 | 1 | Completed | 2013-07-07 12:36:32
5 | 2 | Pending | 2013-07-10 15:05:56
6 | 2 | Reviewing | 2013-07-11 03:08:04
7 | 2 | Implementing | 2013-07-13 11:45:48
8 | 2 | Completed | 2013-07-17 14:28:15
at the gridview I want to display as
request no | request type
SM000004 | aaa
SM000006 | bbb
This is the gridview
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'request-processing-time-grid',
'dataProvider'=>$report->newsearch(),
'filter'=>$report,
'afterAjaxUpdate' => 'reinstallDatePicker', // (#1)
'columns'=>array(
'request_no',
array(
'name' => 'request_type_id',
//'value' => '(in_array($data["request_type_id"], $types) ? $data->requesttypes->name : "1")',
//'value' => '$data["request_type_id"]',
//'value' => $types['$data["request_type_id"]'],
//'value' => '$data->requesttypes->name',
//'value' => '$data["request_type_id"]',
'value' => '$data["request_type_id"].requesttypes.name',
'filter' => $types,
),
),
));
This is the newsearch of model
public function newsearch(){
$query = "SELECT a.request_id, r.request_no, r.request_type_id, r.request_category_id, r.financial_type_id, r.urgency_id,
CONCAT(
FLOOR(HOUR(TIMEDIFF(implementing,reviewing)) / 24), ' days ',
MOD(HOUR(TIMEDIFF(implementing,reviewing)), 24), ' hours ',
MINUTE(TIMEDIFF(implementing,reviewing)), ' minutes') rT,
CONCAT(
FLOOR(HOUR(TIMEDIFF(completed,implementing)) / 24), ' days ',
MOD(HOUR(TIMEDIFF(completed,implementing)), 24), ' hours ',
MINUTE(TIMEDIFF(completed,implementing)), ' minutes') iT
FROM (
SELECT x.request_id
, MAX(CASE WHEN status = 'pending' THEN created_date END) pending
, MAX(CASE WHEN status = 'reviewing' THEN created_date END) reviewing
, MAX(CASE WHEN status = 'implementing' THEN created_date END) implementing
, MAX(CASE WHEN status = 'completed' THEN created_date END) completed
FROM history x
GROUP
BY request_id
) a, request r WHERE r.id = a.request_id ";
$count=Yii::app()->db->createCommand($query)->queryScalar();
$key="request_id";
$dataProvider=new CSqlDataProvider($query, array(
'totalItemCount'=>$count,
'keyField' => $key,
'sort'=>array(
'attributes'=>array(
'request_id' ),
),
'pagination'=>array(
'pageSize'=>10,
),
));
return $dataProvider;
}
This is the relation of the tables
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'requesttypes' => array(self::BELONGS_TO, 'Setup', 'request_type_id'),
'requestcategories' => array(self::BELONGS_TO, 'Setup', 'request_category_id'),
'requestfinanicaltypes' => array(self::BELONGS_TO, 'Setup', 'financial_type_id'),
'requesturgent' => array(self::BELONGS_TO, 'Setup', 'urgency_id'),
'profiles' => array(self::BELONGS_TO, 'Profiles', 'user_id'),
'requests' => array(self::BELONGS_TO, 'Request', 'request_id'),
);
}
The request type is displaying only the request_type_id. I want to display the name of the `setup.name .
How can I do this?
Here I make an example:
You have two tables:
Setup: id, name
Request: id, request_type_id, request_no
In the relations you can define:
'setup' => array(self::BELONGS_TO, 'Setup', 'request_type_id'),
Then when searching
$requests = Request::model()->with('setup')->findAll();
Or if you need any conditions you can apply here.
then you can access the fields like this for each $request in $requests:
$setup_name = $request->setup->name;
If you need to use the dataProvider, you can do something like this:
$criteria = new CDbCriteria;
$criteria->with = array('setup');
$dataProvider=new CActiveDataProvider(Request, array(
'criteria'=> $criteria,
....
));
And then in your gridview you can have:
$data->setup->name
This newsearch of model
public function newsearch(){
$query = "SELECT a.request_id, r.request_no, s1.name request_type, s2.name request_category, s3.name financial_type, s4.name request_urgency,
CONCAT(
FLOOR(HOUR(TIMEDIFF(implementing,reviewing)) / 24), ' days ',
MOD(HOUR(TIMEDIFF(implementing,reviewing)), 24), ' hours ',
MINUTE(TIMEDIFF(implementing,reviewing)), ' minutes') rT,
CONCAT(
FLOOR(HOUR(TIMEDIFF(completed,implementing)) / 24), ' days ',
MOD(HOUR(TIMEDIFF(completed,implementing)), 24), ' hours ',
MINUTE(TIMEDIFF(completed,implementing)), ' minutes') iT
FROM (
SELECT x.request_id
, MAX(CASE WHEN status = 'pending' THEN created_date END) pending
, MAX(CASE WHEN status = 'reviewing' THEN created_date END) reviewing
, MAX(CASE WHEN status = 'implementing' THEN created_date END) implementing
, MAX(CASE WHEN status = 'completed' THEN created_date END) completed
FROM history x
GROUP
BY request_id
) a, request r LEFT JOIN setup s1 ON r.request_type_id = s1.id
LEFT JOIN setup s2 ON r.request_category_id = s2.id
LEFT JOIN setup s3 ON r.financial_type_id = s3.id
LEFT JOIN setup s4 ON r.urgency_id= s4.id
WHERE r.id = a.request_id ";
if(isset($this->request_no))
$query .= " AND r.request_no LIKE '%" . $this->request_no ."%'";
if(isset($this->request_type_id))
$query .= " AND r.request_type_id LIKE '%" . $this->request_type_id ."%'";
if(isset($this->request_category_id))
$query .= " AND r.request_category_id LIKE '%" . $this->request_category_id ."%'";
if(isset($this->urgency_id))
$query .= " AND r.urgency_id LIKE '%" . $this->urgency_id ."%'";
//echo $query;
//die;
$count=Yii::app()->db->createCommand($query)->queryScalar();
$key="request_id";
$dataProvider=new CSqlDataProvider($query, array(
'totalItemCount'=>$count + 1,
//'with'=>array('requesttypes'),
'keyField' => $key,
'sort'=>array(
'attributes'=>array(
'request_id' ),
),
'pagination'=>array(
'pageSize'=>10,
),
));
return $dataProvider;
}
This is cgridview of view
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'request-processing-time-grid',
'dataProvider'=>$report->newsearch(),
'filter'=>$report,
'afterAjaxUpdate' => 'reinstallDatePicker', // (#1)
'columns'=>array(
'request_no',
//'request_id',
array(
'name' => 'request_type_id',
'value' => '$data["request_type"]',
'filter' => $types,
),
array(
'name' => 'request_category_id',
'value' => '$data["request_category"]',
'filter' => $categories,
),
array(
'name' => 'urgency_id',
'value' => '$data["request_urgency"]',
'filter' => $urgencies,
),
array(
'header' => 'Time in Reviewing',
'name' => 'rT',
'value' => '($data["rT"] == NULL) ? "Not Revewing" : $data["rT"]',
'filter' => '',
),
array(
'header' => 'Time in Implementing',
'name' => 'iT',
'value' => '($data["iT"] == NULL) ? "Not Implementing" : $data["iT"]',
'filter' => '',
),
),
));
?>

MySQL: Join a table with multiple line of data

I have 2 tables. The first one contain some global information, and the second contain a list of images.
When I execute this request:
SELECT table1.title, table1.description, table2.image LEFT JOIN table2 ON table2.table1_id = table1.table1_id
Tables structure:
TABLE1
| table1_id | title | description |
| 1 | title1 | description1 |
| 2 | title2 | description2 |
| 3 | title3 | description3 |
TABLE2
| id | table1_id | image |
| 1 | 1 | img/img1.png |
| 2 | 1 | img/img2.png |
| 3 | 1 | img/img3.png |
| 4 | 2 | img/img4.png |
| 5 | 2 | img/img5.png |
| 6 | 3 | img/img6.png |
I got something like that:
<?php
array(
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img1.png'),
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img2.png'),
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img3.png'),
array('title' => 'title2', 'description' => 'description2', 'image' => 'img/img4.png'),
array('title' => 'title2', 'description' => 'description2', 'image' => 'img/img5.png'),
array('title' => 'title3', 'description' => 'description3', 'image' => 'img/img6.png')
);
?>
The problem with this kind of structure is duplicated title, description.
I'd like to get something like that:
<?php
array(
array('title' => 'title1', 'description' => 'description1', 'image' =>
array('img/img1.png', 'img/img2.png', 'img/img3.png')
),
array('title' => 'title2', 'description' => 'description2', 'image' =>
array('img/img1.png', 'img/img2.png')
),
array('title' => 'title3', 'description' => 'description3', 'image' =>
array('img/img6.png')
)
);
?>
My questions are:
Is it possible to get this kind of structure of data just with a SQL request (No PHP manipulation..)
If not, what kind of PHP manipulation I have to do to transform my first array to my second array?
Thanks!
Have a look at group clause and group_concat function. I'm not sure whether it creates an array in PHP, but it's almost what you want:
SELECT table1.title, table1.description, GROUP_CONCAT(table2.image) LEFT JOIN table2 ON table2.id = table1.id GROUP BY table1.id
You can use explode function in PHP to transform the result of GROUP_CONCAT(table2.image) to PHP array
See the documentation of MySQL's group_concat and PHP's explode functions.
You can do a select on all the distinct (Name, Description) tuples. Then you'll have an array of Name,Descriptions, and a null third element. Then loop through this array and get all the images for that distinct tuple. Then take that result and insert it into the third element.
Query get array of name/descriptions:
select distinct table1.title, table2.description left join table2 on table2.id = table1.id
Query to find all images of the distinct name/description tuples:
select table2.image inner join table1 on table1.id = table2.id where table1.name = arr[0] and table1.description = arr[1]
You can quite easily build the structure you're after when you iterate over the results, either was you're going to have to manipulate the result-set.
<?php
$items = array();
foreach ($rows as $row) {
if ( ! isset($items[ $row['title'] ])) {
$items[ $row['title'] ] = array(
'title' => $row['title'],
'description' => $row['description'],
'images' => array($row['image']),
);
continue;
}
$items[ $row['title'] ]['images'][] = $row['image'];
}
$items = array_values($items);
Anthony.
PHP code:
<?php
/*here is your result array*/
$result = array(
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img1.png'),
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img2.png'),
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img3.png'),
array('title' => 'tile2', 'description' => 'description2', 'image' => 'img/img4.png'),
array('title' => 'tile2', 'description' => 'description2', 'image' => 'img/img5.png'),
array('title' => 'tile3', 'description' => 'description3', 'image' => 'img/img6.png')
);
/*creating a new formatted array*/
$newResult = array();
foreach($result as $value){
$newResult[$value['title']]['title'] = $value['title'];
$newResult[$value['title']]['description'] = $value['description'];
$newResult[$value['title']]['image'][] = $value['image'];
}
/*printing new final formatted array*/
print_r($newResult));
?>

How can I convert record set from database to array?

How can I convert record set from database to array?
It has 1 table named: tblproduct, with the following schema:
product_id | product_name | product_desc | product_price | product_img
When I select data from the database I would like an array in the following format:
$product_array = array(
"105" => array('product_id' => '105', 'product_name' => 'Blackberry 8900',
'product_desc' => '', 'product_price' => '1150.00',
'product_img' => 'products/product5.jpg'),
"106" => array('product_id' => '106', 'product_name' => 'Headphone with mic',
'product_desc' => '', 'product_price'=>'148.85',
'product_img' => 'products/product8.jpg')
);
Best regards
Assuming you are using MySQL (You didn't specify your DBMS) and have a line like:
$result = mysql_query('SELECT * FROM `tblproduct`');
You can use:
while($row = mysql_fetch_assoc($result))
$product_array[$row['product_id']] = $row;

Categories