Search from specific to general from large ruleset - php

I have a table that stores price of products in that is hierarchically organized from country level to store level.
create table price_list(
product_id number,
country_id number,
region_id number,
store_id number,
price number
)
I need to search this table to generate invoice. The input for the function (not elaborated here) is in this pattern (i'll use json structure to explain):
{
header : {country_id:5, region_id:234, store_id:345},
items : {
0:{product_id:1001, quantity:5},
1:{product_id:299, quantity:1}
//, etc...
}
}
I want to get the price for the products specific to that store's setup.
Of course if every field is filled, I can search the price by using the complete select syntax.
select price from price_list where product_id = ? and country_id = ? and region_id = ? and store_id = ?
But there are cases where the fields in the table are incomplete, for example only the country_id and product_id is filled because the price is the same for that product in all regions and stores in that country. Let's say I don't want to populate all data with complete fields because of non-technical reasons. A sample data in the table is shown below.
product_id country_id region_id store_id price
1001 3 93 112 15
1001 3 93 113 15.5
1001 4 179 14
1001 4 185 13
1001 5 20
1001 5 999 999 25
Let's take an example if I want to execute this request
{
header : {country_id:5, region_id:300, store_id:500},
items : {
0:{product_id:1001, quantity:5},
}
}
This query will not return a result because country 5 does not specify specific price for each region and store except for region 999 store 999.
select price from price_list where product_id = 1001 and country_id = 5 and region_id = 300 and store_id = 500
Because no row is returned, I need to generalize the search, I start with using all fields, reducing one by one if no price is found.
where product_id = 1001 and country_id = 5 and region_id = 300
But still, this will not return any row. Then I generalized more, and this search gets the value.
where product_id = 1001 and country_id = 5
My current solution is exhaustive. Is there a better way to do this efficiently? The environment is Oracle 11g on php 5.4 and CodeIgniter2.

Why not create a variable which holds the where clause:
$priceWhereclause = "";
$params = [];
if(isset($productIdValue)){
$priceWhereclause .= "product_id = ? ";
$params[] = $productIdValue;
}
if(isset($countryIdValue)){
$priceWhereclause .= "and country_id= ? ";
$params[] = $countryIdValue;
}
Your query would look like:
select price from price_list where $priceWhereclause
put the $params in the execute($params) function.

Related

How is to use eloquent in Laravel with 3 tables?

I have this Database Table which is related to each other
1 customer can have 1 or more tires and 1 tire can have 3 or more test as example below
and I want to get the output of this below using customer_id
I have idea on query builder but I just want to know to use eloquent relation in this case? Anyone can gave me advice?
Can anyone show me example to do this using Eloquent ORM Relationship?
Thankyou
customer_id customer manufacturer trademark test
1 Jeddah Pirelli Str Scorpio High Speed
1 Jeddah Pirelli Str Scorpio Endurance
1 Jeddah Pirelli Str Scorpio Visual
First Table : tbl_customer
id = 1 //unique id
letter_number = 520
customer = Jeddah
Second Table : tbl_tire
id = 1 //unique id
customer_id = 1
manufacturer = Pirelli
trademark = Str Ccorpio
Third Table : tbl_test
id = 1 //unique id
tire_id = 1
customer_id = 1
test = High Speed
id = 2
tire_id = 1
customer_id = 1
test = Endurance
id = 3
tire_id = 1
customer_id = 1
test = Visual
Since you already know customer_id, do this:
$tires = Tire::where('customer_id', $customerId)->with('tests')->get();
This will create 2 queries, but tests will be kind of nested (not like in your example) which is better since it's more comfortable to work with data in this case.

get products which contains both values of filter

my table is
product_id filter_id
55 1
55 2
56 1
57 1
i wants product_id that contains both filter_id 1,2 but not that contains only 1 nor 2.
so my ans is only 55 product_id.
what's my sql query ?
There are a lot of ways to solve it, depends on data amount and more precised conditions. For your particular case this query should fit.
Also, good for you to check docs
select product_id
from my_table
group by product_id
having count(distinct filter_id) = 2
I think this is what you're looking for:
SELECT * FROM products WHERE product_id IN (
(SELECT product_id FROM products WHERE filter_id = 1)
INTERSECT
(SELECT product_id FROM products WHERE filter_id = 2)
);

How to find the sum of two colums with a quantity value

Ok so I am a lil confused how to go about this and seek some help..
I have a mysql db that has a column named quantity and another called price_paid
what I want to do is take and add up the entire column of price_paid but to also take into account a quantity higher than 1.
Ex..
_____________ ______________
| quantity | | price_paid |
-------------- ---------------
1 2.99
2 9.99
1 1.99
How would I create the php / mysql to make that = a total of 24.96 ?
So far I am able to get the total of price_paid but what I have doesn't take into account the quantity column and it's value.
$comic_totals = "SELECT sum(price_paid) AS value_sum FROM `comic_db`.`comic_db`";
$total_db = mysqli_query($comic_connect, $comic_totals);
if(!total_db){
echo "Failed";
}
$tot_array = mysqli_fetch_assoc($total_db);
$sum = $tot_array['value_sum'];
echo "$".$sum;
so how do I turn that into what I need? Thanks
Let MySQL take care of multiplying the price by the quantity...
SELECT SUM(quantity * price_paid) AS value_sum
If you want quantity higher than 1 then add where clause
Like this
SELCET SUM(quantity * price_paid) as value
FROM comic_db.comic_db
WHERE quantity > 1;

MYSQL sort function, depending on the arithmetic operation using the database field values as array keys

I have table of products, and there are 2 fields: price, currency. Possible values in currency fields are 1,2,3. 1 for MDL, 2 for USD, and 3 for EUR. I have to sort my products by price in mdl currency. So i have an array with rates:
$v = array(1,11.38,15.8);
Help my please with my query, I've tried something like this, but I've got errors:
$results = $this->Product
->query("SELECT `id`,`price`,`currency` FROM products
ORDER BY price*$v[currency] DESC");
Hmm... I`ll try to explain, through an example.
My table:
id|price|currency
_________________
1 | 500 | 2
2 | 300 | 3
It shows that first products price is saved in USD, and second products price is saved in EUR. But i have to sort them in MDL valute. So i get an array of rates for each value:
$rates = array([1] = > 1, [2] => 11.50, [3] => 15.50);
So i have to order my products by the result of formula: price*value rate
in first case: 500*$rates['currency value from db, in our case 2] = 500 * 11.50 etc.
Thanks in advance.
Because of the extended example on this problem I have edited this query.
Lets assume that the currencies are alse stored in some table, lets say currency (if not, it should be anyway).
Table currency should be as follows:
ID VALUE CODE
-----------------------------
1 1 USD
2 11.38 EUR
3 15.8 MDL
Then the query should be:
SELECT p.`id`, p.`price`, p.`price` * c.`value` AS 'ratio'
FROM products p
LEFT JOIN currency c ON c.`id` = p.`currency`
ORDER BY `ratio` DESC
By this query You select the currency value from the table currency depending on the currency ID from products table and finaly the results are ordered by the ration price * currency value.
I understand that maybe You have the currencies only hardcoded as array within some config, but it really would be better to put the currencies into the DB (if it is not).
You can`t use data base column name as array keys, because mysql is later instance than php. In php you simply generate query string that is passed to database managment system.
Your query should look like this:
$results = $this->Product->query
(
"SELECT `id`,`price`,
CASE `currency`
WHEN '1' THEN $v[0]
WHEN '2' THEN $v[1]
WHEN '3' THEN $v[2]
END AS 'ratio'
FROM products
ORDER BY price*ratio DESC
"
);

PHP/MySQL: Check if something 'belongs-to' something else?

I have two tables: Stores and Items. The relationship is: Stores 1---* Items
In PHP/MySQL what would be the best (fastest/simplest) way to check if a particular item belongs to a particular store.
In other words given for example:
$store_id = 1;
$item_id = 12;
I want to check if item 12 belongs to store 1 (and not some other store).
I usually do a select on Items matching both the store_id and item_id and limit the results to 1. Then check how many rows (0 or 1) were returned with mysql_num_rows. Is there a better way?
Update:
Both tables have an "id" column. The Items table has a "store_id" column.
SELECT COUNT(*) AS count
FROM stores JOIN items USING(store_id)
WHERE item_id = 12
AND store_id = 1
Then you'd get the results, and check of count > 0 or not. However, if I'm getting your DB design right, then you have a very messed up database.
From what you describe, an item can only exist in one store. So my guess of the general layout here would be like this:
STORE ITEM
----- ----
store_id ---| item_id
store_name |--- store_id
... item_name
...
Is this correct? An item can never exist except in the one store? So if it's a screwdriver, every store would need a different item_id to hold it?
A better design would be:
STORE STORE_ITEM ITEM
----- ---------- ----
store_id ------- store_id |------ item_id
store_name item_id ---| item_name
... ...
With a query of
SELECT COUNT(*)
FROM store JOIN store_item USING(store_id)
JOIN item USING(item_id)
WHERE store_id = 1
AND item_id = 12
Both tables have an id, Items has a store_id
SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id
$r = mysql_query("select NULL from Item where storeID = '$store_id' and ItemID = '$item_id'");
if (mysql_fetch_row($r))
{
it belongs...
}
For fun, I'll throw in a one-liner check:
// if item belongs to store
if (current(mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id"), MYSQL_NUM)))) {
// it belongs!
}

Categories