How to do a "SELECT DISTINCT" with two "INNER JOIN"? - mysql

What I'm trying to do is to GetAPersonByID by doing some inner joins from different tables.
TABLE PEOPLE
IDPerson
Name
LastName
E-mail
fk_ID_Skin
1
Example
Explanation
help#please.com
1
2
Example2
Explanation
ineed#somebody.com
2
TABLE SKINS
IDSkin
Name
1
Normal
2
Weird
TABLE PRODUCTS
IDProduct
Name
fk_skin_type
Photo
1
Oil
1
PhotoOil
2
Water
2
PhotoWater
3
Cream
2
PhotoCream
I need to know which products the CUSTOMER should use according to their SKIN TYPE
But... When I tried to do the InnerJoins (My apologies for the Spanish text in the database):
SELECT
people.IDPerson AS 'Id_person',
people.name AS 'Name',
people.lastname AS 'Lastname',
people.email AS 'E-mail',
skins.name AS 'Skin',
products.name AS 'Product',
products.photo AS 'Photo'
FROM
((people
INNER JOIN skins
ON people.fk_ID_skin = skins.IDSkin)
INNER JOIN products
ON people.fk_ID_skin = products.fk_skin_type)
WHERE IDPerson = c_id;
How can I show 'X Person' without repeating the data?
I'm using MySQL Workbench

How can I show 'X Person' without repeating the data?
It sounds like you are saying you want to see only 1 row per person? Assuming that's the case then I think what you are looking to do is GROUP BY IDPerson. Then you could use the GROUP_CONCAT function in your SELECT statement to generate a comma separated list of the values Foto, Producto, etc.

Related

All records not showing when using a WHERE statement with CONCAT

I have a list of plant, which can be filtered with a CONCAT, originally it was just text, but I have converted it to ID's instead. It was showing all records and could be filtered before I converted to ID's.
This involves 4 tables. (with example data) "" are not used in the fields, they are just to show you that it is a word.
plant
idplant example 1
plantname example "001 Forklift"
idplanttype1 example 1
idlocation1 example 1
iddepartment1 example 1
planttypes
idplanttype example 1
planttype example "Forklift Truck"
locations
idlocation example 1
location example "Preston"
departments
iddepartment example 1
department example "Waste Disposal"
Without the WHERE statement, it shows all records, including nulls. (but the filter doesn't work)
But With the WHERE statement, it is only showing complete records (all of which have no Null fields and the filter works) records with nulls do not show
The issue seems to be the CONCAT. (i've cleaned up the parentheses, but had to add a 1 to make the id's different)
if(isset($_POST['search'])) {$valueToSearch = $_POST['valueToSearch'];}
$sql = "
SELECT idplant, plantname, planttype, location, department
FROM plant
LEFT JOIN planttypes ON idplanttype1 = idplanttype
LEFT JOIN locations ON idlocation1 = idlocation
LEFT JOIN departments ON iddepartment1 = iddepartment
WHERE CONCAT(plantname, planttype, location, department) LIKE
'%".$valueToSearch."%'
ORDER BY plantname";
SOLUTION
The above code works, it was just missing.
WHERE CONCAT_WS
I'm new to Joins, so any help would be greatly appreciated.
Edit: Using Linux Server - Apache Version 2.4.46
Thanks in advance!
Your problem is probably blanks.
WHERE CONCAT(plantname, planttype, location, department)
LIKE '%001 Forklift Forklift Truck Preston Waste Disposal%'
won't find anything for example, as the concated strings result in '001 ForkliftForklift TruckPrestonWaste Disposal', not '001 Forklift Forklift Truck Preston Waste Disposal'.
You want blanks between the substrings, which is easiest to achieve with CONCAT_WS:
SELECT p.idplant, p.plantname, pt.planttype, l.location, d.department
FROM plant p
INNER JOIN planttypes pt ON pt.idplanttype = p.idplanttype1
INNER JOIN locations l ON l.idlocation = p.idlocation1
INNER JOIN departments d ON d.iddepartment = p.iddepartment1
WHERE CONCAT_WS(' ', p.plantname, pt.planttype, l.location, d.department)
LIKE '%001 Forklift Forklift Truck Preston Waste Disposal%'

exact search and similar search combining two tables with multiple keywords mysql

Say I've two tables products and brands having below data.
tbl_products
ID Name BrandID Price
1 Keyboard 1 100
2 Keyboard 2 120
3 Keyboard wireless 1 130
4 Keyboard wireless 2 150
tbl_brands
ID Name
1 Microsoft
2 Dell
3 HP
What I want is when I type 'Microsoft Keyboard' or 'Keyboard Microsoft' then it should list me product ID 1 and 3 not 2 or 4 even 2 or 4 has keyboard. I may search for more keywords but it should give me only the items matching itself.
SELECT p.*, b.Name BrandName FROM tbl_products p INNER JOIN tbl_brands b ON b.ID = p.BrandID WHERE p.Name LIKE '%Microsoft%' OR b.Name LIKE '%Microsoft%' OR p.Name LIKE '%Keyboard%' OR b.Name LIKE '%Keyboard%'
Please help me to write proper MySQL query or any schema change with query..
Appreciate the question. Though I don't have exact answer but surely can discuss one approach to solve the problem.
STEP 1 Get BRAND NAME+NAME as single string.
STEP 2 Tokenise the entered STRING. Example Microsoft Keyboard = Mincrosoft,Keyboard Following Link for spliting the entered data. How do I split a string so I can access item x?
STEP 3 DO a like query on the string obtained in step 1.

How to correctly normalize data set in to tables?

I have a table where first column refers user name other columns refer each subjects that student does and their skill level for each subjects. These subjects are belong to several main subjects streams such as Mathematics, Art and etc.
I normalize the data in to following tables.
Subject_Stream
id Main_Stream Subject
1 Math pure-maths
2 Math applied-maths
3 Art Dancing
4 Art Music
Student_table
id name subject skill_level
1 xxx Music 5
2 xxx Pur-math 4
3 xxx Applied-math 1
4 yyy Music 3
select subjects, skill_level where usename="xxx" order by Desc
I can use a similar query to get subjects and their skill level for any given student.
Apart from, this I need to select students when I select any subject or collection of subjects that do.And print their Name, subjects, skill level in descending order.
Here any student can do different subjects in different streams too.
But I can't easily get this result from my existing tables. How to do this correctly?
Do I need to improve database schema?
First I want to suggest two small improvement for your table structure to better normalize the data. Your table Student_table would be slighly better organized if
instead of name you reference the user_id from your studends-table (that means the name of the student is only present in your studends-table - remember, names can change, p.e. marriage) and
instead of the name of the subject you reference the id of the subject - therefore the name of the subject is only present in your table Subject_Stream.
Your table Student_table would then look something like this:
id user_id subject_id skill_level
--------------------------------
1 1 4 5
2 1 1 4
3 1 2 1
4 2 4 3
Based on this you should be able to get every query you describe. For specifics please update your question and add some examples how your desired results look like, then I'll look into it and give you a few examples.
Apart from, this I need to select students when I select any subject
or collection of subjects that do. And print their Name, subjects,
skill level in descending order.
For a single subject . . .
select name, subject, skill_level
from Student_table
where subject = 'your subject name'
order by skill_level desc, name asc
For multiple subjects . . .
select name, subject, skill_level
from Student_table
where subject = 'some subject name'
or subject = 'some other subject name'
order by skill_level desc, name asc
There are other ways to express this kind of query, but I think multiple OR clauses is the easiest to understand at first.
To select by stream (Math, in this case) . . .
select Student_table.name
, Student_table.subject
, Student_table.skill_level
, subject_stream.main_stream
from Student_table
inner join subject_stream
on subject_stream.subject = student_table.subject
where subject_stream.main_stream = 'Math'
order by Student_table.skill_level desc, name asc

find out count of comma based value in MySql

I have two tables.
Table Emp
id name
1 Ajay
2 Amol
3 Sanjay
4 Vijay
Table Sports
Sport_name Played by
Cricket ^2^,^3^,^4^
Football ^1^,^3^
Vollyball ^4^,^1^
Now I want to write a query which will give me output like
name No_of_sports_played
Ajay 2
Amol 1
Sanjay 2
Vijay 2
So what will be Mysql query for this?
I agree with the above answers/comments that you are not using a database for what a database is for, but here is how you could calculate your table from your current structure in case you have no control over that:
SELECT Emp.name, IF(Played_by IS NULL,0,COUNT(*)) as Num_Sports
FROM Emp
LEFT JOIN Sports
ON Sports.Played_by RLIKE CONCAT('[[:<:]]',Emp.id,'[[:>:]]')
GROUP BY Emp.name;
See it in action here.
UPDATE: added the IF(Played_by IS NULL,0,COUNT(*)) instead of COUNT(*). This means that if an employee doesn't play anything they'll have a 0 as their Num_Sports. See it here (I also added in those ^ characters and it still works.
What it does is joins the Emp table to the Sports table if it can find the Emp.id in the corresponding Played_by column.
For example, if we wanted to see what sports Ajay played (id=1), we could do:
SELECT *
FROM Emp, Sports
WHERE Sports.Played_by LIKE '%1%'
AND Emp.id=1;
The query I gave as my solution is basically the query above, with a GROUP BY Emp.name to perform it for each employee.
The one modification is the use of RLIKE instead of LIKE.
I use RLIKE '[[:<:]]employeeid[[:>:]]' instead of LIKE '%employeeid%. The [[:<:]] symbols just mean "make sure the employeeid you match is a whole word".
This prevents (e.g.) Emp.id 1 matching the 1 in the Played_by of 3,4,11,2.
You do not want to store your relationships in a column like that. Create this table:
CREATE TABLE player_sports (player_id INTEGER NOT NULL, sport_id INTEGER NOT NULL, PRIMARY KEY(player_id, sport_id));
This assumes you have an id column in your sports table. So now a player will have one record in player_sports for each sport they play.
Your final query will be:
SELECT p.name, COUNT(ps.player_id)
FROM players p, player_sports ps
WHERE ps.player_id = p.id
GROUP BY p.name;

SQL GROUP BY - Multiple results in one column?

I am trying to perform a SELECT query using a GROUP BY clause, however I also need to access data from multiple rows and somehow concatenate it into a single column.
Here's what I have so far:
SELECT
COUNT(v.id) AS quantity,
vt.name AS name,
vt.cost AS cost,
vt.postage_cost AS postage_cost
FROM vouchers v
INNER JOIN voucher_types vt
ON v.type_id = vt.id
WHERE
v.order_id = 1 AND
v.sold = 1
GROUP BY vt.id
Which gives me the first four columns I need in the following format.
quantity | name | cost | postage_cost
2 X 5 1
2 Y 6 1
However, I would also like a fifth column to be displayed, showing all of the codes associated with each line of the order like this:
code
ABCD, EFGH
IJKL, MNOP
Where the comma separated values are pulled from the voucher table.
Is this possible?
Any advice would be appreciated.
Thanks
This is what GROUP_CONCAT does.
Assuming the column is called code you would just add ,GROUP_CONCAT(v.code) As Codes to your select list.