I have an array generated with CodeIgniter using MySQL. The values in [co_name] => are duplicated and I tried to group_by it using co_id and its not working ,but it also group_by using order_id.CodeIgniter group_by is working for only one group_by or any other method to removes duplicate values form the [co_name] =>.
Array
(
[0] => stdClass Object
(
[order_date] => 1408255199
[cus_id] => 6
[order_deliver_name] => Jankia
[order_deliver_add_no] => 5085
[order_deliver_add_street] => mapanawathura road
[order_deliver_add_city] => Kandy
[order_deliver_contact] => 0716352632
[order_deliver_date] => 2014-08-12
[order_status] => pending
[emp_id] =>
[cmp_name] => Burger Bun
[co_name] => Put Ham
Put Tomato
Put Ham
Put Tomato
Put Chilli Sauce
Put Tomato
Put Chilli Sauce
Put Ham
Put Chilli Sauce
[order_id] => 28
[quantity] => 10
)
Here is my code
function get_customize_orders(){
$this->db->select(array(
'tbl_order_product_details.order_date',
'tbl_order_product_details.cus_id',
'tbl_order_product_details.order_deliver_name',
'tbl_order_product_details.order_deliver_add_no',
'tbl_order_product_details.order_deliver_add_street',
'tbl_order_product_details.order_deliver_add_city',
'tbl_order_product_details.order_deliver_contact',
'tbl_order_product_details.order_deliver_date',
'tbl_order_product_details.order_status',
'tbl_order_product_details.emp_id',
'tbl_customise_main_product.cmp_name',
'GROUP_CONCAT(tbl_customise_optional.co_name SEPARATOR "<br />" ) as co_name ',
'tbl_order_products.order_id',
'tbl_order_products.quantity',
));
$this->db->from('tbl_order_products');
$this->db->join('tbl_customise_join_products', 'tbl_customise_join_products.cmp_id=tbl_order_products.product_id');
$this->db->join('tbl_customise_main_product', 'tbl_customise_main_product.cmp_id=tbl_customise_join_products.cmp_id');
$this->db->join('tbl_customise_order_products', 'tbl_customise_order_products.order_id=tbl_order_products.order_id');
$this->db->join('tbl_customise_optional', 'tbl_customise_optional.co_id=tbl_customise_order_products.co_id');
$this->db->join('tbl_order_product_details', 'tbl_order_product_details.order_id=tbl_order_products.order_id');
$this->db->group_by('tbl_order_products.order_id');
$query = $this->db->get();
return $query->result();
}
Use DISTINCT in GROUP_CONCAT so it will concatenate only distinct co_name per order_id group
GROUP_CONCAT(DISTINCT tbl_customise_optional.co_name SEPARATOR "<br />" ) as co_name
Related
I have the table products which contains the following:
product_id | name | category | img
1 car toy tcar.jpg
2 boat toy tboat.jpg
3 plane actual plane.jpg
I also have the table product which contains the following:
product_id | size | price
1 large 5
2 small 3
2 medium 4
3 small 7
Finally, I have a multidimensional array called $products_in_cart, with key equal to product_id. It stores the following values:
Array ( [1] => Array ( [Quantity] => 1 [Size] => large) [2] => Array ( [Quantity] => 5 [Size] => medium ) )
I want to inner join products and product and then fetch the products which are found in the array $products_in_cart. (so I will fetch based on the product_id (the keys in $products_in_cart) as well as the size). This has to be done using prepared statements.
I managed to fetch products which are found in $products_in_cart using these statements:
$array_to_question_marks = implode(',', array_fill(0, count($products_in_cart), '?'));
$stmt = $pdo->prepare('SELECT * FROM products WHERE product_id IN (' . $array_to_question_marks . ')');
$stmt->execute(array_keys($products_in_cart));
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
This gives the output:
Array ( [0] => Array ( [product_id] => 1 [name] => car [category] => toy [img] => tcar.jpg) [1] => Array ( [product_id] => 2 [name] => boat [category] => toy [img] => tboat.jpg))
However, what I want is to get this output:
Array ( [0] => Array ( [product_id] => 1 [name] => car [category] => toy [img] => tcar.jpg [size] => large [price] => 5) [1] => Array ( [product_id] => 2 [name] => boat [category] => toy [img] => tboat.jpg [size] => medium [price] => 4))
I expect that I should inner join products and product and then pick those with id's and size that match the ones in $products_in_cart. However I got no clue on how to do that (prepared statements are making the process complicated for me).
I'm sorry for my poor description of the problem, but I hope that the example of what I managed to do makes it clear, thanks!
Well, if you want to do a inner join, just... do an inner join. Nothing says you can't do one within a prepared statement!
Replace this line
$stmt = $pdo->prepare('SELECT * FROM products WHERE product_id IN (' . $array_to_question_marks . ')');
With this one (I'm spliting it in lines for better clarity):
$stmt = $pdo->prepare('SELECT * FROM products
INNER JOIN product
ON (products.product_id = product.product_id)
WHERE products.product_id IN (' . $array_to_question_marks . ')');
You could also use the "shorthand" version if you prefer:
$stmt = $pdo->prepare('SELECT * FROM products, product
WHERE products.product_id = product.product_id
AND products.product_id IN (' . $array_to_question_marks . ')');
As a side note, using two similar named tables is confusing. Since the "product" table contains sizes and prices and no product information, you could rename it to something like "prices_sizes" or something like that.
I'm no amazing with MYSQL at all, however laravel framework has made it very easy for me to get what i need as long as i know the basics.
So this question will first aim towards the MYSQL people, because i would rather figure out how to achieve this in plain MYSQL, and then convert it into laravel queries after.
I have 4 tables that need to be used in this query, as seen below:
1. products
id | name | description | price
2. customers
id | fname | lname | email | telephone
3. orders
id | customer_id | total_price | status
4. order_items
id | order_id | product_id | quantity | price
So i am creating an orders page on my web application. On this page it will show a list of all orders, including the order_items to that particular order. It will also include which customer this order belongs to.
I have managed to achieve the above using laravel, and i get the array seen below:
Array
(
[0] => Array
(
[id] => 9
[customer_id] => 16
[total_price] => 103.96
[status] => new
[created_at] => 2016-02-24 03:06:41
[customer] => Array
(
[id] => 16
[fname] => firstname
[lname] => lastname
[email] => firstname.lastname#gmail.com
[telephone] => 07707707707
[address_line_1] => Warstone Rd, walsall
[address_line_2] => Wolverhampton
[postcode] => WV10 7LX
)
[order_item] => Array
(
[0] => Array
(
[id] => 1
[order_id] => 9
[product_id] => 44
[quantity] => 1
[price] => 50.00
)
[1] => Array
(
[id] => 2
[order_id] => 9
[product_id] => 46
[quantity] => 2
[price] => 31.98
)
[2] => Array
(
[id] => 3
[order_id] => 9
[product_id] => 48
[quantity] => 1
[price] => 7.99
)
[3] => Array
(
[id] => 4
[order_id] => 9
[product_id] => 51
[quantity] => 1
[price] => 13.99
)
)
)
)
Now the part i am having trouble with is getting the products that relate to the order_items.
So far it has worked for me because i have been doing thinking like this
$order = Order::find($id)->with('customer','orderItem')->get()->toArray();
This works easy because an order has a customer_id field and an order_items has an order_id. But for me to get the products i need to join products to order_items.
If any one is good at MYSQL and can provide me a query to study and then convert into laravel that would be great.
If anyone knows laravel 5, well this is all the laravel stuff below:
Order.php
public function customer(){
return $this->belongsTo('App\Customer');
}
public function orderItem(){
return $this->hasMany('App\OrderItem');
}
OrderItem.php
public function order(){
$this->belongsTo('App\Order');
}
public function product(){
$this->hasOne('App\Product');
}
Product.php
public function orderitem(){
$this->hasOne('App\OrderItem');
}
Customer.php
public function orders(){
$this->belongsTo('App\Order');
}
As you can see above are my modal relationships i have set up.
This is my controller where i try to get the full array.
public function show($id)
{
$order = Order::find($id)->with('customer','orderItem','product')->get()->toArray();
echo "<pre>";
print_r($order);
echo "</pre>";
}
The error i receive is:
call to undefined method Illuminate\Database\Query\Builder::product()
If i remove the ->with('customer','orderItem','product') and change it to ->with('customer','orderItem') i get the array posted above.
Does anyone know how i can achieve this please?
You are on the right part the only mistake you are doing is you are calling product on the order model which has no direct relation with it. You have to call the product model through the orderitem model like this
Order::find($id)->with('customer','orderItem.product')->get()->toArray()
I have array below and I need to update database according to this.
It should be something like example code below but I don't know how to do it correctly:
UPDATE productPercent SET percent="$percent" WHERE
store="$store" AND
startDate>"$start_date" AND
endDate<"$end_date" AND
storeGroup="$storeGroup" AND
productGroup="$product_group" AND
productName LIKE '$search%'
I need to check for each store, store group, product (if contains word) and product group and then update productPercent table. Percent, product group, store group, product name and store are in different tables so some kind of inner join is needed.
I need some directions regarding this because I don't know how to start, thank you.
Array
(
[percent] => 3
[store] => Array
(
[0] => 36
[1] => 45
[2] => 56
)
[start_date] => 2015-02-09
[end_date] => 2015-03-31
[storeGroup] => Array
(
[0] => 2
[1] => 4
)
[product_group] => Array
(
[0] => 13
[1] => 31
[2] => 32
)
[search] => iphone
[setPercent] => Submit
)
UPDATED: data model - tableName: columns(connected tables)
store: id,name,startDate,endDate
storeGroup: id,storeGroupID(in table storeGroupName: id,name),storeID
productGroup: id,productID(in table productName: id,name),groupID(in table productGroupName: id,name)
productName: id,name
productPercent: id,productID,storeID,percent
$pdoHandle = $this->getPDOHandle();
$searchword = 'iphone';
$sql = "UPDATE
productPercent
inner join store on productPercent.storeID=store.id
inner join storeGroup on storeGroup.storeID=store.id
inner join productGroup on productGroup.id=storeGroup.groupID
inner join productName on productPercent.productID=productName.id and productGroup.productID=productName.id
SET percent=:percent
WHERE productName.name like :searchword";
$pdo->prepare($sql);
$pdo->setAttribute('percent', floatval($percent/100));
$pdo->setAttribute('searchword', $searchword . '%');
I'm trying to code a search function for a site written on CodeIgniter but have trouble with the join statement in the model.
A controller passes an array of search criteria to the model function: get_sales($search_criteria);
function get_sales($search_criterie){
$this->db->join('sales_prices', 'sales_prices.sale_id = sales.sale_id', 'left');
$this->db->join('sales_sizes', 'sales_sizes.sale_id = sales.sale_id', 'left');
$query = $this->db->get_where('sales', $search_criterie);
$sale_data = $query->result_array();
}
I'm running into two problems:
1) I need a WHERE clause in the sales_sizes join. Right now it joins sales_sizes.sale_id ON sales.sale_id but I want to be able to filter by size via the $search_criteria array. How can I do this?
2) Every sales usually has multiple sizes and I want the output of the query formatted like:
Array
(
[sale_id] => 1
[sale_category] => shoes
[sale_price] => 29.99
[sale_sizes] => Array
(
[0] => 10
[1] => 10.5
[2] => 11
)
)
I've tried some foreach loops to format the output but can't get it to work. Hope somebody can help.
Update:
How do I process the following query result into a format like the one above?
Array
(
[0] => Array
(
[sale_id] => 1
[sale_category] => shoes
[sale_price] => 29.99
[sale_size] => 10
)
[1] => Array
(
[sale_id] => 1
[sale_category] => shoes
[sale_price] => 29.99
[sale_size] => 10.5
)
[2] => Array
(
[sale_id] => 1
[sale_category] => shoes
[sale_price] => 29.99
[sale_size] => 11
)
)
I am personally not a big fan of using the active record as given. I find that it often restricts the programmer from writing more complex queries. If you find that this is true as well you could rewrite your query as followed:
$this->db->query('SELECT * FROM `sales_prices`, `sales_sizes` WHERE `sales_prices`.`sale_id` = `sales`.`sale_id` AND `sales_sizes`.`sale_id` = `sales`.`sale_id` AND `sales` = ?', array($search_criterie));
$sale_data = $query->results();
This will generate the same result and will also parameterize your query. Note that the question mark corresponds in order to values in your array that will make up the second parameter of you $this->db->query() function.
Try this type of query
$this->db->select('places.*, category.*')
->from('places')
->join('category', 'places.category_id = category.category_id', 'left')
->join('places_reviews', 'places_reviews.place_id = places.id', 'left')
->where('places.category_id', $category_id)
->limit($limit, $offset)
->order_by($sort_by, $sort_order);
The below solution will work for you, it won't generate exact output, but very close to one.
$this->db->select('sales.*, GROUP_CONCAT(DISTINCT sales_prices.sale_id) as sales_price GROUP_CONCAT(DISTINCT sales_sizes.sale_id) as sales_size')
This will generate a comma separated value for you.
ok so i have this query
select ss.system_step_id, ss.step_number, cd.name, ssp.system_step_product_id, p.cost, ssp.class_id from system_step ss
join system as s on s.system_id=ss.system_id
join category_description as cd on cd.category_id=ss.sub_category_id
join system_step_product as ssp on ss.system_step_id=ssp.system_step_id
join product as p on p.product_id=ssp.product_id where s.system_id = 41
order by ss.step_number, ssp.class_id;
which yields this result
7 1 Screens 808 115.0000 1
7 1 Screens 809 381.9000 2
7 1 Screens 810 441.9000 3
8 2 Printers 811 112.3200 1
8 2 Printers 812 201.0400 2
8 2 Printers 813 202.8700 3
9 3 Cash Drawers 814 135.7000 1
9 3 Cash Drawers 815 86.5400 2
9 3 Cash Drawers 816 135.7000 3
Is there a way to turn this into a php array of three elements like this
Array
(
[0] => Array
(
[name] => "Screens"
[standard_product] => Array ([id] => 808, [price] => '115.0000')
[business_product] => Array ([id] => 809, [price] => '381.9000')
[premium_product] => Array ([id] => 810, [price] => '441.9000')
)
[1] => Array
(
[name] => "Printers"
[standard_product] => Array ([id] => 811, [price] => '112.3200')
[business_product] => Array ([id] => 812, [price] => '201.0400')
[premium_product] => Array ([id] => 813, [price] => '202.8700')
)
[2] => Array
(
[name] => "Cash Drawers"
[standard_product] => Array ([id] => 814, [price] => '135.7000')
[business_product] => Array ([id] => 815, [price] => '86.5400')
[premium_product] => Array ([id] => 816, [price] => '135.7000')
)
)
$sql = "select ss.system_step_id, ss.step_number, cd.name, ssp.system_step_product_id, p.cost, ssp.class_id, pd.name as product_name, pd.description from system_step ss join system as s on s.system_id=ss.system_id join category_description as cd on cd.category_id=ss.sub_category_id join system_step_product as ssp on ss.system_step_id=ssp.system_step_id join product as p on p.product_id=ssp.product_id join product_description as pd on pd.product_id=p.product_id where s.system_id = {$system['system_id']} order by ss.step_number, ssp.class_id;";
$result = mysql_query($sql);
$steps = array();
while($row_r = mysql_fetch_assoc($result)){
$steps[] = $row_r;
}
so steps is the the full array with 9 elements
As you can see the only thing of note is the class_id 1 is standard_product class_id 2 is business_product and class_id 3 is premium_product
You can fetch fill a multi-dimensional array while fetching the SQL result or split into several SQL commands and therefore build up your array (1st fetching the names, than the products with values of every name).
I do not know which you prefer but as you have a large join splitting the SQL might not be the worst in terms of readability of your code. Performance impact may vary.
Methinks this will do it
<?php
$finalArray = array();
$nameArray = array('Screens', 'Printers', 'Cash Drawers');
foreach ($nameArray as $name) {
while ($row = mysql_fetch_assoc($result)) {
if ($row['name'] == $name) {
if ($row['class_id'] == 1) {
$standard = array('id' => $row['system_step_product_id'], 'price' => $row['cost']);
}
else if ($row['class_id'] == 2) {
$business = array('id' => $row['system_step_product_id'], 'price' => $row['cost']);
}
else if ($row['class_id'] == 3) {
$premium = array('id' => $row['system_step_product_id'], 'price' => $row['cost']);
}
}
}
array_push($finalArray, array('name' => $name, 'standard_product' => $standard, 'business_product' => $business, 'premium_product' => $premium,));
}
?>
Hopefully I got all the column names right.
This is what I tested it off of and I get the correct output http://codepad.org/yjU3gxbB
The only thing you may what to change is creating the name array dynamically
while ($row = mysql_fetch_assoc($result)) {
array_push($nameArray, $row['name']);
}
$nameArray = array_unique($nameArray);
However, PHP doesn't like it when you do a mysql_fetch_assoc twice on the same query. You might want to do another query where you only select the cd.name