Join 4 tables with common field in Codeigniter - mysql

I have four tables named tblproducts, tblprospecification, tblcomspecification and tblledtvpecification.
The fields of tblproducts are proid, product_code, product_name,
pro_img, pro_resize_img, pro_thumb_img and it stores products
details.
The second table is tblprospecification stores the mobile specifications and it has column speid, proid, in_the_box ,model_number, model_name, color, browse_type, sim_type.
The third table is tblcomspecification for storing computer specification and its column are comspecificid,proid, modelname, color, series etc. and the fourth column istblledtvpecification for storing ledtv specification and its column are tvspecificid, modelname, dsize, stype_id, hd_techno.
I am using the query below enter
$query= $this->db->select( 'tblproducts.proid as pro_id, product_code, product_name, pro_img, pro_resize_img, pro_thumb_img, tblprospecification.proid as product_id , in_the_box ,model_number, model_name, tblprospecification.color as mobile_color, browse_type, sim_type ,tblcomspecification.proid as product_id, tblcomspecification.modelname as com_moledname, series, tblcomspecification.color as com_color, tblledtvpecification.proid, tblledtvpecification.modelname as ledtv_modelname, dsize,stype_id, hd_techno')
->from('tblproducts')
->join('tblprospecification','tblproducts.proid = tblprospecification.proid ' ,'left')
->join('tblcomspecification','tblproducts.proid = tblcomspecification.proid', 'left')
->join('tblledtvpecification','tblproducts.proid = tblledtvpecification.proid' ,'left')
->where('tblproducts.proid',$proid)
->get();
return $query->result();
When I execute the query, it will return the data after join from tblproducts and tblprospecification only. It returns blank data for tblledtvpecification, tblcomspecification.

Related

Mysql query from a third table

I have a database with Orders, Order_content and Vendors table. I want to get the vendors in one order.
Vendor(vid, company_name, phone_number)
Order_content(ocid, product_name, vid)
Order(oid, ocid, address, name, phone_number)
I want to get the company_name, address and phone_number from the Vendor table that are related to a specific order.
What I have tried.
SELECT vendor.company_name, vendor.address, vendor.phone_number FROM vendor WHERE vendor.vid = order_content.vid AND order_content.oid = order.oid;
Using JOIN
SELECT vendor.company_name, vendor.address, vendor.phone_number AS vendor_details
FROM vendor
INNER JOIN orders_content ON (vendor.vid = orders_content.vendor_id AND orders_content.oid = orders.oid)
WHERE vendor.id;
The SQL is wrong and not working, some help will be appreciated. I think I am supposed to use a JOIN, I tried but the SQL throws an error.
Thanks.
You are only joining Vendor and Order_content, but not Order, so you are missing some fields as a result:
SELECT vendor.company_name, vendor.address, vendor.phone_number AS vendor_details
FROM vendor
INNER JOIN orders_content ON (vendor.vid = orders_content.vendor_id AND orders_content.oid = orders.oid)
INNER JOIN order ON (orders_content.ocid = orders.ocid);
Note that I removed the where clause, since it did not make any sense.

laravel join with average of a column in another table

I have a Food model and Review model. in my reviews table in database I have two columns : food_id and rate. Each user can rate foods and rate is an integer number between 1~5.
I need to get all records in foods table and average of rate column in reviews where food_id is the id of each food.
$foods = Food::join('reviews', 'foods.id', '=', 'reviews.food_id')->select(
'foods.*',
'AVERAGE(reviews.rate) WHERE reviews.food_id = foods.id AS food_rate'
)->get();
And of course this code will raise SQLSTATE[42000]: Syntax error
How can I join with average of a column in another table?
SELECT foods.*, AVG(reviews.rate) AS food_rate
FROM foods
LEFT OUTER JOIN reviews
ON reviews.food_id = foods.id
GROUP BY foods.id
in fact this MYSQL code needs to be written with Laravel
$foods = Food::select(
'*',
\DB::raw('AVG(reviews.rate) AS food_rate'),
)->leftJoin('reviews', 'foods.id', '=', 'reviews.food_id')->groupBy('foods.id');
and we need to set 'strict' => false in config/database.php

Using union in codeigniter query builder, and filter in a virtual mysql column

In my project I am using datatables plugin with serverside processing. It works fine untill i do a search or order(sort) operation because it needs active record to do that.
My scenario is, i have an account table, revenue table and payment table, and I want to view all the data of revenue and payment table, thats why I need a union. my query is like below---
SELECT 'Income' as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created
FROM tbl_revenue JOIN tbl_accounts as ta on tbl_revenue.fld_account_id = ta.fld_id
UNION
SELECT 'Expense' as source, fld_type, fld_amount, tae.fld_account, fld_date, tbl_payment.fld_description as fld_traninfo, tbl_payment.fld_created as created
FROM tbl_payment JOIN tbl_accounts as tae on tbl_payment.fld_account_id = tae.fld_id
Is there any way to use query builder in this query?
And second question, you can see I created a virtual column named 'source', i want to filter this column using where clause with append this query like below
WHERE source like "%a%" limit(10,0)
But this returns that I don't have any column name 'source', how can I filter this column?
Any help is appreciated.
there is a way to do that but its a bit hacky because codeigniter's querybuilder adds an auto SELECT statement to the query if you didn't specify it by yourself
In order to get what you want, you've to split your select statements in 2 queries and add the where clause to this query
Something like that should work:
$strQuery1 = $this->db
->select('income as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created')
->from('tbl_revenue')
->join('tbl_accounts as ta', 'tbl_revenue.fld_account_id = ta.fld_id')
->get_compiled_select();
$strQuery2 = $this->db
->select('Expense as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created')
->from('tbl_payment')
->join('tbl_accounts as ta', 'tbl_revenue.fld_account_id = ta.fld_id')
->get_compiled_select();
$strWhere = substr($this->db->like('source', 'a', 'both')->get_compiled_select(), 8);
$query = $this->db->query($strQuery1.' UNION '.$strQuery2.$strWhere);

How to select data in MySQL from the same table based on conditions and avoid duplicates?

I have read related answers, but I did not find a solution to my problem. Please help me with the following issue: I have two tables and I want to match them based on tenors, but considering the fact that in one table I can have different entries satisfying this condition. In the table from which I want to extract the information (inst), I have several data regarding the interest rates, all structured on different lines, e.g. I can either have LIBOR or OIS data.
I would like to do the following query: to match the tenors from the second table (stgy) with the data from the first table (inst) for the OIS where available, and otherwise, to have the LIBOR data.
Below a code that I tried and did not work:
SELECT CASE
WHEN stgy.tenor IN ('1D','1W','2W','3W','1M','2M','3M','4M','5M','6M','7M','8M','9M','10M','11M')
THEN ( CASE WHEN security_type='OIS' THEN
(SELECT price_last FROM inst WHERE currency = #base_crncy AND trade_date = #date_of_interest AND tenor = stgy.tenor)
ELSE
(SELECT price_last
FROM inst
WHERE security_type IN ('LIBOR') AND currency = #base_crncy AND trade_date = #date_of_interest
)
END AS rate
)
ELSE NULL
END AS int_rate
I am also matching on the same trading day and currency. Please consider that I can have other security_type as well. Thank you for your help!
Updated query:
SELECT CASE WHEN stgy.tenor IN('1D','1W','2W','3W','1M','2M','3M','4M','5M','6M','7M','8M','9M','10M','11M')
THEN (COALESCE((SELECT price_last FROM instruments WHERE security_type='OIS' AND currency=#base_crncy AND trade_date = #date_of_interest AND tenor=stgy.tenor),
(SELECT price_last FROM instruments WHERE security_type='LIBOR' AND currency = #base_crncy AND trade_date = #date_of_interest AND tenor=stgy.tenor))
)
ELSE NULL
END AS int_rate
-- and here i add from where based on the join between the tables (this part works)
First, to simplify, you appear to want to query from your "stgy" table just for the specific base currency AND the "tenor" values in the list.
SELECT
s.tenor
FROM
stgy s
WHERE
s.currency = #base_crncy
AND s.tenor IN ('1D', '1W', '2W', '3W', '1M', '2M', '3M', '4M',
'5M', '6M', '7M', '8M', '9M', '10M', '11M')
from that, you want the rate from the "inst" table on same tenor, currency and date of trade. Now, to get the last price, it is based on the SECURITY TYPE.
SELECT
s.tenor,
COALESCE( i.price_last, i2.price_last ) as Price_Last
FROM
stgy s
LEFT JOIN inst i
ON s.currency = i.currency
AND s.tenor = i.tenor
AND i.trade_date = #date_of_interest
AND i.securityType = 'OIS'
LEFT JOIN inst i2
ON s.currency = i2.currency
AND i2.trade_date = #date_of_interest
AND i2.securityType = 'LIBOR'
WHERE
s.currency = #base_crncy
AND s.tenor IN ('1D', '1W', '2W', '3W', '1M', '2M', '3M', '4M',
'5M', '6M', '7M', '8M', '9M', '10M', '11M')
To help optimize the query, I would include an index on
stgy ( currency, tenor )
inst ( currency, trade_date, tenor, security_type )
Syntax for creating the indexes...
ALTER TABLE `stgy` ADD INDEX `currency_tenor` (`currency`, `tenor` );
ALTER TABLE `inst` ADD INDEX `cur_trade_ten_sec` (`currency`, `trade_date, `tenor`, `security_type` );
Now, you may need to tweek the condition for:
AND case when s.securityType = 'OIS'
then s.tenor = i.tenor
else s.security_type IN ('LIBOR') end
as you do not show table structures, nor sample data (you can edit your original question to provide such SAMPLE data.
Also, you mention preventing duplicates... By duplicates, do you mean multiple entries for a given currency, trade_date, tenor, security type (also unsure which table your "security_type" field is actually associated with).
I modified by doing TWO left-joins to the inst table. Please confirm the required criteria respectively. It looked like your "OIS" criteria required the join on the "tenor" field too, but NOT for the "LIBOR" value. But notice the left joins are explicitly on EITHER the "OIS" or "LIBOR" respectively so there should not be multiple entries for a given OIS/TENOR, nor a duplicate on LIBOR per given date/currency.
Then, the price is pulled via COALESCE(). If the first value is NULL, then grab the value from the second column. If that too is null, your final column answer would be null which is what you intended to get.

Mysql total amount (price) in cart from many tables

I met what I believe is a very common problem with mysql and e-commerce shop ... though I can't find answer for this.
I've got shop which has not one product table but many ... for example in one shop has vinyls, studio gear etc ... so we've got many tables with different product details ... the thing is I need to get total amount (price) of products in cart from many tables
public static function GetTotalAmount() {
$params = array(
':cart_id' => self::GetCartId()
);
$sql = 'SELECT SUM(v.price) AS total_amount '.
'FROM shopping_cart sc '.
'INNER JOIN vinyl v '.
'ON sc.product_id = v.id AND sc.department_id = 1 '.
'WHERE sc.cart_id = :cart_id AND sc.buy_now;';
$v = DataBase::FetchOne($sql, $params);
$sql = 'SELECT SUM(sg.price) AS total_amount '.
'FROM shopping_cart sc '.
'INNER JOIN studio_gear sg '.
'ON sc.product_id = sg.id AND sc.department_id = 2 '.
'WHERE sc.cart_id = :cart_id AND sc.buy_now;';
$sg = DataBase::FetchOne($sql, $params);
return $sg + $v;
}
As you might see I made this with ugly way .. maybe you can help me show how to get SUM() of possible N tables counted from N.price.
You can use UNION ALL
SELECT SUM(price) FROM ((SELECT SUM(price) as price FROM table1 WHERE ...) UNION ALL (SELECT SUM(price) as price FROM table2 WHERE ...) UNION ALL ....)
A quick tip (if you can) - merge all the products tables into one table and operate on that (you'll also have to implement categories and custom attributes for products though). Otherwise you will have a mess when you add new shops.
You can create a (materialized) view with just the necessary columns of the product tables, - product_id and price
Once you have the view (vw_products) you can just do an inner join of shopping cart table with the view and then get the sum.
SELECT sum(vw.price) FROM
shopping_cart sc INNER JOIN vw_products vw
ON sc.product_id = vw.id and sc.department_id IN (1,2,...)
WHERE sc.cart_id = :cart_id AND sc.buy_now;
If you have many rows and if the prices don't change often (every few minutes)
I would suggest creating a table and populating it with the result of above query.
Every day or after every change to price you can refresh this table.