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.
Related
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.
I am working on a php/mysql best before date checking system and upon creating a new check I need the system to find a best before date for a certain product by looking for it most recent closed check
I am working with a few tables to get this done:
bbcheckProducts
ID checkID productID checked bestBefore
1 1 1 1 2015-05-06
2 2 1 1 2016-07-22
3 3 1 1 2016-09-16
bbChecks
checkID userID closed
1 1 1
2 2 1
3 1 1
So when I run this query on the tables in the image above:
SELECT ID,
MAX(checkID) AS maxCheck,
bestBefore
FROM bbcheckProducts
WHERE checkID IN
(
SELECT checkID
FROM bbChecks
WHERE userID = 1
AND closed = 1
)
AND checked = 1
GROUP BY productID
ORDER BY bestbefore ASC
it returns something like this:
ID = 1
maxCheck = 3
bestBefore = 2015-05-06
so it does take the max checkID but the other values remain equal to the first occurence of productID. I want it to take the values that go together with that max ID so the result would look like this:
ID=3
maxCheck = 3
bestBefore = 2016-09-16
so how do I get my query to work like that?
NOTE: there are multiple products so product one may be in check 1 and 3 while product 2 is only in 1 so it has to take the data of product 2 from check 1 and the data of product 1 from check 3
You need to use max function on second table like this query
select * from table_name where some_colomn = 'some_value' and some_colomn
in (select max(some_colomn) from table_name2 where some_col = 'some_value' group by some_colomn)
You could join your tables to get a reduced set of all record with an check_ID existing in your bbChecks-table.
Then you can run your max(CheckID)-selection on the reduced set.
In your case this would like like that:
SELECT ID, max(checkID), bestBefore
FROM bbcheckProducts p
INNER JOIN bbChecks c ON (p.checkID = c.checkID)
WHERE UserID = 1
AND closed = 1
AND checked = 1
This returns you first of alle the records with the checkIDs 1 and 3. And then you select the max(checkID), so it returns you the checkID 3.
My ch_skills table looks like
uid | skill1 | skill2 | skill3 | skill4 | skill5
1 1 2 2 0 1
2 1 1 2 1 1
3 1 2 3 0 1
My first question: is this correct? I mean would it be better if I made it like this:
uid | skillid | skill_lvl
1 1 1
1 2 2
1 3 2
1 4 0
1 5 1
Everything worked fine until now with the example #1, but now I'm in a trouble with the sql queries. Currently, I'm using 5 different queries to get the level of each skill. I use the following code:
For skill1:
$query = $this->db->prepare("SELECT `skills`.`skill_ID` as `Skill1_id`,
`skill_name`.`skill_name` as `Skill1_name`, `skill_level` as `Skill1_level`,
`skill_price` as `Skill1_price`
FROM `skills`, `skill_name`, `ch_skills`
WHERE `skill_name`.`skill_ID` = `skills`.`skill_ID`
AND `skills`.`skill_ID`= 1
AND `skills`.`skill_level` = `ch_skills`.`skill1`
AND `ch_skills`.`uid` = :uid");
For skill2:
$query = $this->db->prepare("SELECT `skills`.`skill_ID` as `Skill1_id`,
`skill_name`.`skill_name` as `Skill1_name`, `skill_level` as `Skill1_level`,
`skill_price` as `Skill1_price`
FROM `skills`, `skill_name`, `ch_skills`
WHERE `skill_name`.`skill_ID` = `skills`.`skill_ID`
AND `skills`.`skill_ID`= 2
AND `skills`.`skill_level` = `ch_skills`.`skill2`
AND `ch_skills`.`uid` = :uid");
And so on... As you can see, there's only two differences: skill_id = 2, and skill2 as the coulmn's name. Is there any way for querying all the 5 skills in only 1 query? Or would you recommend me anyway to change the table structure?
Note: skills stands for the skill prices, and skill_name for the skill's names.
As the other commenters have suggested, your best choice is to change the table exactly as you proposed.
The biggest reason not to have a wide table like you show in your first example, is that adding a skill means changing the structure of the database, which could break existing queries.
Secondly, as you see when you're trying to query the results, having a single table doesn't even make it easier to work with.
The only possible benefit to a non-normalized table like your example is that it takes up slightly less disk space. But in todays world, disk space should never be your primary concern.
To answer your question about querying the original non-normalized example, however, there are two ways to do it:
Use a union statement which would combine 5 distinct queries together. This is pretty inefficient
Create a table with (in this case) 5 rows (or if you have a Skills table use that). Then join the ch_skills table to that, which should take each row and split it 5 times. See below: (note: I'm assuming for the purposes of this example that skills and skill_name are in a 1:1 relationship and only have 5 records each)
SELECT skills.skill_ID,
skill_name.skill_name,
skill_level as Skill_level,
skill_price as Skill_price
FROM skills
JOIN skill_name on skill_name.skill_ID = skills.skill_ID
JOIN ch_skills
WHERE ch_skills.uid = :uid
AND ((skills.skill_ID = 1 AND skills.skill_level = ch_skills.skill1)
OR (skills.skill_ID = 2 AND skills.skill_level = ch_skills.skill2)
OR (skills.skill_ID = 3 AND skills.skill_level = ch_skills.skill3)
OR (skills.skill_ID = 4 AND skills.skill_level = ch_skills.skill4)
OR (skills.skill_ID = 5 AND skills.skill_level = ch_skills.skill5))
Currently I have 3 MySQL tables, one filed with the users information, one with their course history and the last one filled with their reward history.
I am attempting to create a "rewards" program if you will, using these two databases and a PHP script. As far as the reward requirements, I have 2 arrays setup for the two types of rewards:
//Pen Reward with course A & B required
$pen=array("a","b")
//Cup Reward with course B & C required
$cup=array("b","c")
I can't figure out how to first query for all user IDs, then go through their history. If they match the requirements set above, then to update the reward table to 1 (to show that they received the award)
UsersDB
userid name
----------------
1 bill
2 john
3 steve
HistoryDB
userid courseid
------------------
1 a
1 b
2 b
3 a
3 c
RewardHistoryDB
userid pen cup
---------------------
1 0 0
2 0 0
3 0 0
Ideally it after the PHP script runs, it would update the RewardHistoryDB to reflect that user 1 received a pen, and user 3 received a cup.(the DB would look like this:)
RewardHistoryDB (after)
userid pen cup
---------------------
1 1 0
2 0 0
3 0 1
Here is the PHP code I am using right now (not complete):
$userid=array();
$i=0;
//Find All users
$result = mysqli_query($con,"SELECT userid FROM usersdb")
while ($row = mysqli_fetch_array($result)){
$universityid[$i]=$row['universityid'];
$i++;
}
//Find History
$courseid=array();
foreach ($userid as $userid1){
$result = mysqli_query($con,"SELECT courseid FROM historydb WHERE userid='".$userid1."'");
while ($row = mysqli_fetch_array($result)){
$courseid[]=$row;
}
}
//Update Reward DB
//Don't even know where to start...
Any help would be greatly appreciated.
If you have any questions, please let me know.
Thank you in advanced!
http://sqlfiddle.com/#!2/1a96b/1/0
You can do this just as queries and without doing any logic in PHP
update RewardHistoryDB
set Pen = 1
where UserID in (
select UserID
from HistoryDB
where CourseID in ('A','B')
group by UserID
having count(UserID)=2);
update RewardHistoryDB
set Cup = 1
where UserID in (
select UserID
from HistoryDB
where CourseID in ('B','C')
group by UserID
having count(UserID)=2);
Or you can even do it in one, large statement...
update RewardHistoryDB
left outer join (
select UserID as Pens_UserID
from HistoryDB
where CourseID in ('A','B')
group by UserID
having count(UserID)=2 ) as Pens
on RewardHistoryDB.UserID = Pens.Pens_UserID
left outer join (
select UserID as Cups_UserID
from HistoryDB
where CourseID in ('B','C')
group by UserID
having count(UserID)=2 ) as Cups
on RewardHistoryDB.UserID = Cups.Cups_UserID
set Pen = case when Pens.Pens_UserID is not null then 1 else 0 end,
Cup = case when Cups.Cups_UserID is not null then 1 else 0 end
I am working on project which is in symfony 1.0
I have problem in creating propel query.
I have two table
car
id name
1 a
2 b
3 c
feature
id car_id feature
1 2 f1
2 2 f2
3 2 f3
4 1 f1
5 3 f3
6 3 f2
7 3 f4
Here is a SQLFiddle with table and value.
I have feature array(f1,f2,f3). Now I want only cars which has all three features i.e which is "b" in our case.
I have tried but not gives satisfied result
$c = new Criteria();
$c->clearSelectColumn();
$c->addSelectColumn(CarPeer::NAME);
$c->addSelectColumn(FeaturePeer::CAR_ID);
$c->addJoin(CarPeer::ID,FeaturePeer::CAR_ID,Criteria::LEFT_JOIN);
$c->add(FeaturePeer::FEATURE,array(f1,f2,f3),Criteria::IN);
$c->addGroupBy(CarPeer::ID);
$resultset = CarPeer::doSelectRs($c);
I believe this is the SQl you want (seems to work in my SQL Fiddle anyway):
SELECT car_id FROM
(SELECT COUNT(car_id) AS feature_count, car_id FROM feature
WHERE feature IN ('f1', 'f2', 'f3') GROUP BY car_id
) car_features
WHERE car_features.feature_count=3
Now to get that in Propel you need to do something like:
$features = array("f1", "f2", "f3");
$featureCount = FeatureQuery::create()
->withColumn("COUNT(car_id)", "feature_count")
->add(FeaturePeer::FEATURE, $features, Criteria::IN)
->addGroupBy(CarPeer::ID);
$cars = CarQuery::create()
->addSelectQuery($featureCount, "car_features")
->where("car_features.feature_count = ?", sizeof($features))
->find();