Mysql query IN clause - mysql

I have two tables.
One is where the price of ice cream is saved in different currency and another where which ice cream for the respective currency id is added by user to buy.
icecreamprice
id icecream_id name currency_id price
1 3 white_chocolate 2 3
2 3 white_chocolate 4 10
3 11 dark_chocolate 2 6
4 3 white_chocolate 3 4
Here id is pk and auto increment, icecream_id is being saved from a table where ice cream names and their respective id is mentioned.
cart
id icecream_id user_id price_id(type=TEXT)
1 3 111 1,4
So i want to fetch everything from both icecreamprice and cart table when icecreamprice_id is present in cart_price_id and cart user_id is 111.
so this is my query
"SELECT id,icecream_id,name,price,c.user_id FROM icecreamprice ic,cart c WHERE c.user_id=111 and ic.id IN (c.price_id)"
But seems like this query is not effective, its fetching only one row insteam of two rows from first table

You can't use IN on a text string in MySQL, but you can use FIND_IN_SET instead:
SELECT ic.id, ic.icecream_id, ic.name, ic.price, c.user_id
FROM icecreamprice ic
JOIN cart c ON FIND_IN_SET(ic.id, c.price_id)
WHERE c.user_id=111
Output:
id icecream_id name price user_id
1 3 white_chocolate 3 111
4 3 white_chocolate 4 111
Note that I have made your JOIN explicit and added the condition to the JOIN for clarity.
Demo on dbfiddle

Related

MySQL substring to self join

I'm defining the relationship between the two tables using a join table. I want to arrange them in the order of many overlapping things. Currently, we are using subquery, is there a way to get the same result using join?
People FoodTable PeopleFood
ID | NAME ID | Food ID | PeopleId | FoodId
1 BOB 1 Hamberger 1 1 1
2 JOHN 2 Pizza 2 1 2
3 KATY 3 Chicken 3 1 3
4 MILLER 4 Salad 4 2 1
5 AMANDA 5 Sushi 5 2 2
6 2 3
7 3 2
8 3 3
9 4 3
10 4 5
11 5 5
When the table is defined in this way, I want to arrange food tastes similar to Bob's.
I'm doing it like this now.
SELECT people_id, COUNT(people_id) as count
FROM peopleFood
WHERE food_id IN
(SELECT food_id FROM peopleFood
WHERE people_id = 1)
AND people_id != 1
GROUP BY people_id
ORDER BY count DESC;
-- Result -------------
People_id | count
2 3
3 2
4 1
Is there a better way to change this method or use join?
Thank you!!!
You have been inconsistent in your use of the table and column names -
Tables - PeopleFood in your sample data but you reference peopleFood in your query.
Columns - PeopleId and FoodId in your sample data but you reference people_id and food_id in your query.
Choose a naming convention and stick to it. Everyone has there own preference but the important thing is to be consistent.
The equivalent query with INNER JOIN instead of your sub-query is -
SELECT
`pf2`.`people_id`,
COUNT(`pf2`.`food_id`) as `count`
FROM `PeopleFood` `pf1`
INNER JOIN `PeopleFood` `pf2`
ON `pf2`.`people_id` <> `pf1`.`people_id`
AND `pf2`.`food_id` = `pf1`.`food_id`
WHERE `pf1`.`people_id` = 1
GROUP BY `pf2`.`people_id`
ORDER BY `count` DESC;
The performance difference between the two queries is unlikely to be noticeable and it might be argued that the intent is clearer in your version with the sub-query.
The surrogate key ID on your PeopleFood table should be dropped in favour of the compound “natural” primary key on people_id and food_id.
The Cost of Useless Surrogate Keys in Relationship Tables
Inner join:
SELECT p.People_id, COUNT(p.People_id) as count FROM PeopleTable p
INNER JOIN FoodTable f
ON(p.People_id = f.FoodId)
WHERE people = 1
GROUP BY p.people_id
ORDER BY count DESC;
If it helps, please mark it as an accepted answer!

Fetch rows which belonging to the parent category which has more than two rows

I have some combination of company and members
Member Table
id company_id companymember
1 1 john
2 1 Tam
3 2 haya
4 1 lee
5 3 kih
6 3 wild
7 3 cream
8 3 earth
What I want to pick up is
the 3 member names which belonging to the company which has more than two members
What I want is like this
company_id 2 has only 1 member, 3rd row is not selected
company_id 3 has 4 members, so 8th row is not selected
My Goal
1 1 john
2 1 Tam
4 1 lee
5 3 kih
6 3 wild
7 3 cream
I could make it , pick up company_ids first and
loop each id by script and fetch.
However in this way, it exec sql many times.
Is there any good way to do this on MySql by one sentence SQL??
Try this
select id,company_id,companyMember
from (Select id
,company_id
,companyMember
,Row_Number() OVER(PARTITION BY company_id ORDER By company_id) AS TotalCount
from MemberTable
) as Table1
where TotalCount <=3 and Company_id in(
Select Company_id
from MemberTable
group by Company_id
having COUNT(Company_id) >=3
)
order by id

Count Category products with mysql

I have to count products inside each category like I have a category A that have two childs B and C.
In B category have 10 products and C category have 5 Products.
I want to write a query that count product like A = 15 B = 10 C = 5.
I have wrote a query that count only for child categories.
My query is given below
SELECT
c.`id`,
c.`parent_id`,
c.`name`,
c.`slug`,
c.`route_id`,
c.`description`,
c.`excerpt`,
c.`sequence`,
c.`image`,
c.`seo_title`,
c.`meta`,
c.`enabled`,
(SELECT
COUNT(`product_id`)
FROM
HM_category_products
WHERE
HM_category_products.category_id IN (SELECT
HM_categories.`id`
FROM
HM_categories
WHERE
(id = c.`id` OR id = c.`parent_id`))) AS count
FROM
`HM_categories` AS c
EDITED :- Below is my tables structure. This is just an example.
Category Table
id parent_id name slug enabled
1 0 Mobiles & Tablets mobiles-tablets 1
2 1 Mobile Phones mobile-phones 1
3 1 Tablets tablets 1
4 1 Mobile Accessories mobile-accessories 1
5 0 Electronics & Computers electronics-computers 1
6 5 Cameras & Accessories cameras-accessories 1
7 5 TV - Video - Audio tv-video-audio 1
Category Product Table
product_id category_id
1 2
2 2
3 2
4 2
5 3
6 2
7 3
8 3
9 3
10 2
11 3
12 2
13 2
14 2
15 2
You hav to use the "Group by" with something like:
SELECT
category_id, COUNT(*)
FROM
HM_category_products
GROUP BY category_id
This would get your table HM_category_products Grouped by category_id so will know how mane rows of each category its in the table, whats mean you will know the number of product of each category. Then you can join this resulting table with category one to get the category info. (Sorry for my english)
The GROUP BY statement is used in conjunction with the aggregate
functions to group the result-set by one or more columns. SQL GROUP BY Statement
for more info abaut "Group by" read
12.16.2 GROUP BY Modifiers and
12.16.1 GROUP BY (Aggregate) Functions
EDIT: I see now what you whant. I already give you the direction but here its a step furder: DISCLAIMER: THIS QUERY ITS JUST EXAMPLE, IT DOSNT WORK
CREATE VIEW view_2 AS
SELECT
category_id, COUNT(*) AS product_sum
FROM
HM_category_products
GROUP BY category_id
CREATE VIEW view_1 AS
SELECT
*
FROM
HM_categories
LEFT JOIN
view_2 AS a ON HM_categories.id = a.category_id;
SELECT
id,
name,
(SELECT
SUM(product_sum)
FROM
view_1
WHERE
parent_id = final.id) as product_count
FROM
HM_categories AS final;
that way you will get the product of a parent category, your only missing a CASE on the last select "product_count" to the child categorys, but that sum its easy because you already hav it on the view_1 (again sorry for my english)

mysql select in another select group: how many people in downline?

Hello i've a table similar to this one:
id sponsor name
------------------------
1 0 Sasha
2 1 John
3 1 Walter
4 3 Ashley
5 1 Mark
6 4 Alexa
7 3 Robert
8 3 Frank
9 4 Marika
10 5 Philip
11 9 Elizabeth
when i choose an ID (call it MYCHOICE) i want know all the name of people who has sponsor like MYCHOICE... is simply:
select * from tablename where sponsor=MYCHOICE
but... here is the problem... i would know how many people there is in the downline of this results... so... how many records there are with sponsor like each id.
if i choose id 1 result should be
id name downline
----------------------
2 John 0 (noone with sponsor=2)
3 Walter 3 (3 with sponsor=3: ashley, robert, frank)
5 Mark 1 (1 with sponsor=5: philip)
if i choose id 4 result should be
id name downline
----------------------
6 Alexa 0
9 Marika 1 (1 with sponsor=9: Elizabeth)
i try this "bad solution" if mychoice is 1
select sponsor,count(*) as downline from tablename where sponsor in
(select id from tablename where sponsor=1) group by sponsor order by
downline desc
result of this query is
sponsor downline
---------------------
3 3
5 1
there are 2 problems:
- names are not rights and is not that i want
- the count 0 "2|John|0" in the example dont appears
thank u for advice and help, sorry for english,
N.
SELECT child.id,
child.name,
COUNT(grandchild.sponsor) downline
FROM TableName child
INNER JOIN TableName parent
ON child.sponsor = parent.id AND
parent.id = ? -- << user choice
LEFT JOIN TableName grandchild
ON child.id = grandchild.sponsor
GROUP BY child.id, child.name
SQLFiddle Demo
As you can see, the table is joined to itself twice. The first join that uses INNER JOIN gets the records associated with the Sponsor which is your user_choice. The second join which uses LEFT JOIN gets all the records associated with records from your user_choice.

MySQL Join Multiple (More than 2) Tables with Conditions

Assume I have 4 tables:
Table 1: Task
ID Task Schedule
1 Cut Grass Mon
2 Sweep Floor Fri
3 Wash Dishes Fri
Table 2: Assigned
ID TaskID (FK) PersonID (FK)
1 1 1
2 1 2
3 2 3
4 3 2
Table 3: Person
ID Name
1 Tom
2 Dick
3 Harry
Table 4: Mobile
ID PersonID (FK) CountryCode MobileNumber
1 1 1 555-555-5555
2 2 44 555-555-1234
3 3 81 555-555-5678
4 3 81 555-555-0000
I'm trying to display the
Task on a certain day
Name of person assigned to task
Phone numbers of said person
I think it should be something like the following, but I'm not sure how to set up the conditions so that the results are limited correctly:
SELECT T.ID, T.Task, P.Name, M.MobileNumber
FROM Task AS T
LEFT JOIN Assigned AS A
ON T.ID = A.TaskID
LEFT JOIN Person AS P
ON A.PersonID = P.ID
LEFT JOIN Mobile AS M
ON M.PersonID = P.ID
WHERE T.Schedule = Fri
My goal is to fetch the following information (it will be displayed differently):
Tasks Name MobileNumber
Sweep Floor, Wash Dishes Dick, Harry 44-555-555-1234, 81-555-555-5678, 81-555-555-0000
Of course, if JOIN is the wrong way to do this, please say so.
It's unclear what you want to do with duplicate data in this case, but you should be looking at using inner joins instead of outer joins, and using something like group_concat() to combine the phone numbers.