Based on user input, which could be a single or multiple values, and using the following table
+------+--------+
| seed | item |
+------+--------+
| 1 | apple |
| 1 | grapes |
| 2 | apple |
| 3 | grapes |
| 3 | banana |
+------+--------+
I want to return
1 when the user entered (apple, grape),
[1, 2] for (apple), and
nothing for (apple, banana).
My current PHP code
$keyword = Input::get('keyword');
$searchTerms = explode(",", $keyword);
$query = DB::table('items');
foreach($searchTerms as $term)
{
$query->where('item', 'LIKE', '%'.$term.'%');
}
$results = $query->distinct()->get(array('seed'));
works for single values. Iterating in the loop, I'm just appending more search terms to the current $query. At the end, I need to find the intersection of all the queries. This is currently my main concern.
With the input available try
SELECT seed
FROM Items
WHERE item IN ('apple', 'grapes')
GROUP BY seed
HAVING COUNT(item) >= 2
;
SELECT seed
FROM Items
WHERE item IN ('apple')
GROUP BY seed
HAVING COUNT(item) >= 1
;
SELECT seed
FROM Items
WHERE item IN ('apple', 'banana')
GROUP BY seed
HAVING COUNT(item) >= 2
;
The total to compare against in the HAVING clause is the count of items, you are checking in the respective batch.
SQL Fiddle
Please comment, if further detail or adjustment is required.
Related
I have two MySQL tables, first, is house and second one family, The house table has two columns called house_id and house_name while the second table has three columns family_id, member_name the last column in the family table used to reference house_id from first table this is house_id
CONCEPT:
How can get number of family_members with/who come from a certain house and put the counted number in the HTML table by fetching only on house table?
I created the following script to fetch from house,
SELECT * FROM house;
And I manipulated the fetched data using foreach like this,
$mystmt = $db -> prepare('SELECT * FROM house');
$mystmt->execute();
$myresult = $mystmt->fetchAll();
foreach($myresult as $mydata) {
$myarray = array();
$myarray[] = $mydata['house_id'];
$myarray[] = $mydata['house_name'];
$output[] = $myarray;
}
echo json_encode($output);
On the above code i get only two columns the house_id and house_name, Now how can i adjust this code to count from family table so that I can get another column called total_family_members
Just like this
family_id | member_name | house_id
1 | John Jackson | 1
2 | Ketty Bebe | 2
3 | Maam Juke | 1
4 | Tike Nuke | 2
5 | Carol Michael | 2
Desired result
house_id | house_name | total_family_members
1 | Joh's house| 2
2 | kim's house| 3
In your example, two different processes are involved:
Link everyone's house id to the house name. This can be achieved with a JOIN.
Count the number of people in each house. This can be achieved with a GROUP BY and a COUNT.
Here is a solution:
SELECT house.house_id , house.house_name , COUNT( * ) AS total_family_members
FROM house
INNER JOIN family ON family.house_id = house.house_id
GROUP BY family.house_id
User table:
User_id(Pk,AI) | First_name | Last_name
1 | John | Doe
2 | Peter | Griffin
3 | Donald | Duck
Item table:
Item_id(PK,AI) | Owner(FK - user_id) | Item_name
1 | 1 | Shoes
2 | 2 | Pants
3 | 3 | Shirt
Item_review table:
Item_review_id(PK,AI) | Item(FK - item_id) | Reviewer(FK - user_id) | Rating |
Content
1 | 1 | 2 | 4 | Great
With the Tables above, There are three things i want to check before inserting a row into the review table.
Check if reviewer is not the item owner(cannot review own item or biased review)
Form validation(if reviewer inputted anything into the rating and content)
Check if review exists(no duplicate review or only one review per user)
That's my procedure, I've done the other two except the first one as i am unsure and confused on how to do this.
I could simply use a get where query like:
public function check_biased_review($user_id, $item_id){
$this->db->select('*');
$this->db->from('item');
$this->db->where('item_id', $item_id);
$this->db->where('owner', $user_id);
$query = $this->db->get();
if($query->num_rows() > 0){
return TRUE;}
else{
return FALSE;}
}
I actually solved this by writing the code above, i had this misconception that i would have to query so many rows if there are many reviews to find the matching rows that i forgot about the where clause in the first place which will do it in the db instead of doing it in the model function with an foreach loop and an if statement. I guess you have to code first instead of having assumptions and never doing it to check or you could waste time like i did.
But my first solution was to use a join query. $item_id and $user_id is passed from the controller to the model.
How would i go about joining the tables to get the same result?
I just try to give you an join query example below.
$this->db->select('*');
$this->db->from('Item_review');
$this->db->join('User','Item_review.user_id = User.User_id');
$this->db->join('Item','Item_review.item_id= Item.Item_id');
$this->db->where('item_id', $item_id);
$this->db->where('owner', $user_id);
$query = $this->db->get();
I want to get result of joining multiple tables as one row and fetch multiple cuisine_name from t_cuisine table and get the cuisine_id in t_search.cuisineId column using php (CODEIGNITER) and joins
t_search table to get the cuisineId like this so that I can get the available cuisine names through the cuisineId.
t_search table
searchID|restaurant_name|cuisineId
1 | XYZ | 1,4,5
2 | KIH | 2
3 | GHY | 4,5
4 | UIO | 1,2,3
5 | RTY | 3,5
t_cuisine table
cuisineId|cuisine_name
1 | ABC
2 | CDE
3 | EFG
4 | GHZ
5 | HJL
in my Model i've used
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_cuisine','t_cuisine.cuisineId = t_search.cuisineId');
which fetches data only based on single value in cuisineId in t_search.
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_cuisine','t_cuisine.cuisineId IN(t_search.cuisineId)');
$this->db->where('t_cuisine.cuisineId', X);
Change X to the ID of the cuisine you are looking for
What you had previously (when your query worked based on a single value in cuisineId) was a one to many relationship. Joining like that worked well because each search had one cuisine.
This is a many to many relationship, and this table structure doesn't support it well. Instead of storing a delimited list in the cuisineId column of your t_search table, you need another table to represent the relationship between search and cuisine, like this:
t_search_cuisine table
searchID|cuisineId
1 | 1
1 | 4
1 | 5
2 | 2
3 | 4
3 | 5
4 | 1
4 | 2
4 | 3
5 | 3
5 | 5
Then you should be able to get all your data with one additional join.
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_search_cuisine','t_search.searchID = t_search_cuisine.searchID');
$this->db->join('t_cuisine','t_search_cuisine.cuisineId = t_cuisine.cuisineId');
Based on the structure of your table, joining those table would be not easy. Perhaps you could do with two queries instead.
$this->db->select("cuisineId");
$this->where("searchID", $searchID);
$qry1 = $this->db->get("t_search");
$res1 = $qry1->row_array();
$qry1->free_result();
if ($res1) {
$this->db->select("*");
$this->db->where_in('cuisineId', $res1);
$qry2 = $this->db->get("t_cuisine");
$res2 = $qry2->result();
return ($res2) ? $res2 : false;
}
I have a table that contains some ingredients. Example:
id | title | ingredients
1 | ex1 | ketchup, chicken, salt, honey, mountain dew
2 | ex2 | beef, pepper, chili, honey, salt
And when the user searchs for the ingredients like:
ketchup, salt, honey
I generate a sql-query:
select * from recipes where(
(ingredients LIKE '%ketchup%')
AND (ingredients LIKE '%salt%')
AND (ingredients LIKE '%honey%')
And it returns all recipes containing these specific ingredients, and it works grey.
Now. I've added a range-slider, to pick how many of the entered ingredients that should match for the search to return anything. Lets say i chose that 2 ingredients should match at least, i want to make a PHP function that outputs a sql string that pairs everyone of the entered ingredients, but i simply don't have the mindset for it.
Example:
(ingredients LIKE '%ketchup%') AND (ingredients LIKE '%salt%')
OR
(ingredients LIKE '%ketchup%') AND (ingredients LIKE '%honey%')
OR
So on. So ketchup & salt pair, ketchup & honey pair, salt & honey pair.
And of course variable so theres no limit to the ingredients inputted. I've tried for hours but no success. Hope i've explained my self clearly & someone will be able to help or teach me something :-)
My php function that does the current string looks like this:
$c_soeg = "ketchup, whatever, whatever. etc";
$c_ing_arr = explode(",", $c_soeg);
$c_count_arr = count($c_ing_arr);
$i = 0;
$c_sql = "SELECT * FROM recipes WHERE (";
while($i < $c_count_arr){
$c_sql .= "(ingredients LIKE '%".trim($c_ing_arr[$i])."%')";
if($i != $c_count_arr-1){
$c_sql .= " AND ";
}
$i++;
}
$c_sql .= ")";
And the variable that contains the value of the range is named
$c_range;
Instead of AND and OR conditions count the met criteria. This example gives you all records where at least two ingredients match:
select * from recipes
where
case when ingredients like '%ketchup%' then 1 else 0 end
+
case when ingredients like '%salt%' then 1 else 0 end
+
case when ingredients like '%honey%' then 1 else 0 end
> = 2;
I think you should make 3 tables meaning
one for the title and another for the ingredients and one to connect them
recipy
id | title |
1 | ex1 |
3 | ex2 |
recipyingredients
recipyid | ingredientsid
1 | 1
1 | 2
1 | 3
1 | 4
1 | 5
2 | 1
2 | 6
2 | 7
ingredients
id | ingredients
1 | ketchup
2 | chicken
3 | salt
4 | honey
5 | mountain dew
6 | beef
7 | pepper
In that case one recipy can have many ingredients and viceversa
The database would be clearer and you would not have to use like % as much.
Also you do not have to write the same ingredients every time for a recipy
I have the following table and want to know how to set up a column total to calculate the sum of the row. I want the total column to calculate first_bid - second_bid.
id | First Bid | Second Bid | Total
0 | 7 | 1 | (first_bid)-(second_bid)
1 | 8 | 2 |
2 | 5 | 3 |
3 | 4 | 4 |
4 | 5 | 5 |
5 | 5 | 6 |
I need to display to the user all previous bids and total on a page. The total should be in descending order also.
SELECT id, First_Bid, Second_Bid, First_Bid - Second_Bid AS Total
For the grand total, you'd have to run a second query with SUM() aggregate functions. Which is somewhat redundant, since you can just do the summation in your client as you retrieve the data. e.g.
$total = 0;
while($row = fetch_from_db($result)) {
$total += $result['Total'];
... display row data ...
}
... display total ...
You can just calculate the total when you are querying the database.
SELECT first_bid, second_bid, (first_bid - second_bid) as total FROM table ORDER BY 3 DESC
Something along these lines
Try this query:
SELECT *, (First Bid-Second Bid) as total from TABLE