Mysql "where" and "and" statement from multiple rows [duplicate] - php

This question already has answers here:
Query to find posts with an exact set of tags (many-to-many relationship)
(2 answers)
Closed 9 years ago.
I have 3 tables:
users
+---------+
|id | name|
+---------+
|1 | Tom |
|2 | Adam|
+---------+
skills
+------------+
|id |name |
+------------+
|1 |baking |
|2 |driving|
|3 |etc |
+------------+
users_skills
+-----------------+
|user_id |skill_id|
+-----------------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
+-----------------+
So in result I have two users:
Tom has 1 and 2 skill
Adam hass 1 and 2 and 3 skill
I want to get all users that have exactly skill 1 and 2, so I want to get Tom. How to achieve that?
If I wanted to get users with skill 1 OR skill 2 - it's not a problem, but AND it is :(
Basically I tried to join users with users_skills table, but I get something like this:
+-----------------------+
|user_id |name |sill_id|
+-----------------------+
|1 |Tom | 1 |
|1 |Tom | 2 |
+-----------------------+
etc
so I have two rows and I don't know how to achieve AND statement here.

Here is the solution. The tricky part is the fact that not only has to match those skills but also NOT match any out of them.
SELECT u.id, u.name, us.skill_id FROM users u
JOIN users_skills us ON u.id = us.user_id
WHERE u.id IN (
SELECT user_id FROM users_skills
WHERE user_id NOT IN (
SELECT user_id FROM users_skills
WHERE skill_id NOT IN (1, 2)
)
GROUP BY user_id
HAVING COUNT(DISTINCT skill_id) = 2
)
Fiddle here. Note I've also added additional users and skills to test all cases.
In short: You first get rid of the ones that have additional unwanted skills and then you get rid of the ones that have less than the needed skills.
Output:
| ID | NAME | SKILL_ID |
|----|------|----------|
| 1 | Tom | 1 |
| 1 | Tom | 2 |

You need the DISTINCT function (and GROUP BY):
SELECT DISTINCT(u.name)
FROM users AS u
JOIN users_skills AS us
ON u.id = us.user_id
WHERE us.skillID IN (1,2)
GROUP BY u.id

Related

Get all the data from a table and sometimes relate that table with another

My question is: Can I do this?
I try many things, some of them are:
Search 1
Search 2
Search 3
Search 4
I need all the info form Table A, and sometimes I need to join this table with Table B. My problem is that when I join both tables, if an specific parameter in Table A is not in Table B just give me the records when the specific parameter are, but I want all the records.
Table A
|--------------------------------|
| Table A |
|-------------------|------------|
| id_table_A | name | id_table_B |
|------------|------|------------|
| 1 | Joe | 1 |
|------------|------|------------|
| 2 | Ben | |
|------------|------|------------|
| 3 | Lya | |
|------------|------|------------|
| 4 | luis | 2 |
|------------|------|------------|
Table B
|----------------------|
| Table B |
|----------------------|
| id_table_B | Elements|
|------------|---------|
| 1 | Car |
|------------|---------|
| 2 | Byke |
|------------|---------|
| 3 | Moto |
|------------|---------|
What I want to show in my View is this:
|------------|------|------------|
| id_table_A | name | Elements |
|------------|------|------------|
| 1 | Joe | Car |
|------------|------|------------|
| 2 | Ben | |
|------------|------|------------|
| 3 | Lya | |
|------------|------|------------|
| 4 | luis | Byke |
|------------|------|------------|
My model
In my model this is what I tried:
"SELECT * FROM table_A, table_B where table_A.id_table_B = table_B.id_table_B"
But this query only show me data 1 and 4.
This can be done or not?
Thanks in advance.
You can use left join
SELECT *
FROM table_A
left join table_B on table_A.id_table_B = table_B.id_table_B
Left join is used when the keys between tables may not always match. In this case, the left join retrieves the correct match where it's possible and the values become NULL when not possible.
SQL LEFT JOIN Documentation
You need an explicit LEFT JOIN as opposed to the implicit INNER JOIN that is used when you simply list the tables like that. https://www.w3schools.com/sql/sql_join_left.asp

count number of rows that have the same combination of two colums

Hi I have 2 table Offense table and User_jobs table
offense table:
crime_id |crime_type |casenumber|
---------+-----------+----------+
1 | 3 |1 |
2 | 3 |1 |
1 | 3 |2 |
12 | AA |2 |
user_jobs table:
casenumber |disposal_status |
-----------+----------------+
1 | yes |
1 | yes |
2 | no |
2 | no |
what i want is to count the number of rows with the same combination say crime_id=1 and crime_type= 3 but these must have a disposal status of yes in the user_jobs table.
i want to do this in mysql. pliz help
sorry but i am new to mysql. i now want to display the real names of those id not the id themselves.
the tables with these IDs are crime_category and Crime_type Crime_catgory
table:
category |crime_id |
-----------+----------------+
theft | 1 |
murder | 2 |
rape | 3 | 2 |
no |
Crime_type table:
Crime_type |id |
---------------+----------------+
administrative | yes |
criminal | yes |
You can do this with a simple inner join and an aggregate function:
select
o.crime_id,
o.crime_type,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type
This will pick up distinct combinations of the first two columns joined as they should tot he jobs table and only where the disposal_status is equal to 'Yes'
Edit: You would probably do really well to have a read of this Q&A that I put together for exactly this sort of situation - where I give you the code for it, but would like to explain this is a lot more detail. The Q&A explains why this type of thing (and many many others) work and how they do so:
How can an SQL query return data from multiple tables
Edit 2:
select
o.crime_id,
o.crime_type,
ct.category,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
join crime_type ct
on o.crime_type=ct.crime_id
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type,
ct.category,

Join two tables with one table has multiple rows matching

Trying to figure out if it is possible to create a query where you join tables, table one is smaller than table two, table two has multiple references matching table one entries, the query would output a joining where table one length is preserved but you just add more columns. Not sure if that makes sense so here is a example of what I am after
Table One Table two
+-----------------------------+ +-----------------------------+
| id | english | definition | | id | word_id | sentence |
+-----------------------------+ +-----------------------------+
|1 | A1 | blah | |1 | 1 | blahblah1 |
|2 | B4 | blah2 | |2 | 1 | blahblah2 |
+-----------------------------+ |3 | 1 | blahblah3 |
|4 | 2 | blahblah4 |
|5 | 2 | blahblah5 |
+-----------------------------+
********* Query should return something like *****************
+----------------------------------------------------------------+
| id | english | definition | sentence | sentence2 | sentence3 |
+----------------------------------------------------------------+
|1 | A1 | blah | blahblah1| blahblah2| blahblah3 |
|2 | B4 | blah2 | blahblah4| blahblah5| |
+----------------------------------------------------------------+
My Current query looks like this and results in:
$query = "SELECT * FROM T1 INNER JOIN T2 ON T1.id = T2.word_id";
Resulting in:
+----------------------------------------+
| id | english | definition | sentence |
+----------------------------------------+
|1 | A1 | blah | blahblah1|
|1 | A1 | blah | blahblah2|
|1 | A1 | blah | blahblah3|
|2 | B4 | blah2 | blahblah4|
|2 | B4 | blah2 | blahblah5|
+----------------------------------------+
I am working with PHP and MySql.
UPDATE!!
Staying with my original query and manipulating the results with PHP getting good performance too. Let me know if you need me to post my code.
You might be looking for GROUP_CONCAT()
SELECT T1.id, T1.english,T1.definition,
GROUP_CONCAT(T2.sentence ORDER BY T2.ID SEPARATOR '|')
FROM Table1 T1 INNER JOIN Table2 T2 ON T1.id = T2.word_id
Group by word_id
Sample fiddle
The answer is NO. Simply because there's unknown number of columns (say, if you add one more sentence to the top word you could be adding one more column to the result set) and each column is not well defined ( Why blahblah4 should be in column sentence instead of sentence2 ?)
IMO, SQL is used to tell what you want to get, but in this case, SQL is unable to tell exactly what you want.
Even if this can be done ( I would love to learn ), I believe the complexity offsets any benefit and handling this in PHP is a better option.

How to return the first value from groups in one database table, MySQL

I have a table called photos in a MySQL database that contains photo filenames and other related info. Structure as follows:
+----------+------------+-------------+
| photo_id | gallery_id | photo_fname |
|----------|------------|-------------|
| 1 | 1 | DSC2001 |
| 2 | 1 | DSC2002 |
| 3 | 1 | DSC2003 |
| 4 | 2 | DSC2004 |
| 5 | 2 | DSC2005 |
| 6 | 2 | DSC2006 |
| 7 | 3 | DSC2007 |
| 8 | 3 | DSC2008 |
| 9 | 3 | DSC2009 |
+----------+------------+-------------+
What I want to do is write a query that returns the first photo filename for each gallery, as follows:
+----------+------------+-------------+
| photo_id | gallery_id | photo_fname |
|----------|------------|-------------|
| 1 | 1 | DSC2001 |
| 4 | 2 | DSC2004 |
| 7 | 3 | DSC2007 |
+----------+------------+-------------+
I researched this until my headache overcame me last night and although I found similar questions, they didn't seem to me to be looking to do the exact same thing. I tried subqueries, I tried the sample code from other posts here but couldn't make it work. Either due to brain fog or just not finding the right solution.
I just want to return the results as shown above, nothing more.
Many thanks in advance!
UPDATE:
My apologies, the table name is photos, FWIW.
Secondly, all I really want is the filename, not the photo or gallery Id, I just included those for visual clarity. I apologize if that caused confusion.
Try this:
SELECT *
FROM YourTable
WHERE photo_id IN ( SELECT MIN(photo_id)
FROM YourTable
GROUP BY gallery_id)
See a demo
For your updated question:
SELECT photo_fname
FROM photos
WHERE photo_id IN ( SELECT MIN(photo_id)
FROM photos
GROUP BY gallery_id)
Here is an easy way using inner join
SELECT
m.*
FROM sparkles as m
INNER JOIN (SELECT
photo_id,
MIN(photo_id)
FROM sparkles
GROUP BY gallery_id) as l
on l.photo_id = m.photo_id
Demo
SELECT photo_id, gallery_id, photo_frame
FROM ...
GROUP BY photo_id, gallery_id
by default, mysql will return the FIRST non-grouped value it encounters in the DB for any non-aggregated fields in the field list.
Select * from tablename group by gallery_id; ?

query to imlement block list

I have two tables a and b as follows to implement a simple block list where users can block other users.....
Table A
+------------+--------------+------+
| Name | phone |userid|
+------------+--------------+------+
| Mr Sasi | 01225 708225 | 1 |
| Miss Brown | 01225 899360 | 2 |
| Mr Black | 01380 724040 | 3 |
+------------+--------------+------+
Table B
+------------+--------------+
| blockedbyid| blockedid |
+------------+--------------+
| 1 | 2 |
| 2 | 3 |
| 1 | 3 |
+------------+--------------+
"blockedbyid" is id of user who has blocked the user in "blockedid".
I need to join the two tables and fetch all records from table A such that the result has all users who are not blocked by a particular user [ie blockedbyid='XXX'].. Can you guys give the SQL query so that i can fetch the records as a recordset??? I dont want to fetch two different rowsets and compare it in php....
Something like this should work
Parameter :USERID
SELECT * FROM TABLEA WHERE userid NOT IN (SELECT blockedid FROM TABLEB WHERE blockedbyid = :USERID)
Using join
SELECT u.* FROM TABLEB b, TABLEA u WHERE b.blockedbyid = 'XXX' AND b.blockedid = NULL
It may work like that, give it a try.
Roadie57 solutions seems better though.

Categories