Selecting rows with reference id's to same table - mysql

I have a table call user such as below:
id name ref_id
-- ---- ------
1 Sam 0
2 Jack 1
3 Sue 2
4 Sam2 1
5 Sue2 3
6 Sam3 1
7 Alan 3
8 Tom 3
9 Lyn 2
10 Van 1
I want to select the user have referred 3 people.
Is it possible to write a query and select this:
Name
--
Sam
Sue

You can use self join like below
SELECT a.`name` FROM ref a LEFT JOIN ref b
ON a.id = b.ref_id
GROUP BY a.name
HAVING COUNT(b.id) >2
Try this Demo

you can use query below:
select Count(u1.name) unit,u1.name from ref as u1 INNER JOIN ref as u2 ON u1.Id = u2.ref_id
group By u1.id
having unit > 3
you can replace unit > 3 to unit > 2

Related

Join table two column as 1 column

May I know how to join two columns table into as 1 column?
For example:
Edited
first_table
id | folder | category id | status
1 Peter 5 0
2 John 6 1
3 Shawn 7 0
second_table
id | filename| category id
1 123.sql 9
2 you.png 12
3 it.pdf 11
I want expected result like below, column folder and filename become store in 1 column and
column name as folder_filename :
First table join Second table
id | folder_filename| category id | status
1 Peter 5 0
2 John 6 1
3 Shawn 7 0
4 123.sql 9
5 you.png 12
6 it.pdf 11
I tried below this sql, but not sure how to modify make it work.
SELECT * FROM first_table INNER JOIN second_table
Hope someone can guide me how to solve it. Thanks.
You seem to want union all:
select f.id, f.folder, f.category_id
from first_table f
union all
select s.id, s.folder, s.category_id
from second_table s;
EDIT:
If you actually want to change the ids, then:
select row_number() over (order by which, id) as id, folder, category_id
from ((select f.id, f.folder, f.category_id, 1 as which
from first_table f
) union all
(select s.id, s.folder, s.category_id, 2
from second_table s
)
) fs
) fs

Multiple rows with 2 condition in the same column MySQL

How to select multiple rows with 2 condition in the same column MySQL
students' table:
id name
1 Jhon
2 Anne
3 Charles
4 Bob
lesson_contract's table:
id lesson_code student_id
1 L1 1
2 L2 1
3 L1 2
4 L1 3
5 L2 3
6 L2 4
So i want to get student that take both lesson_code L1 and L2. So the result should be Jhon and Charles
You could do this by joining into the lesson_contract table twice, once for each lesson code:
SELECT s.id, s.name FROM students s
INNER JOIN lesson_contract l1
ON s.id = l1.student_id AND l1.lesson_code = 'L1'
INNER JOIN lesson_contract l2
ON s.id = l2.student_id AND l2.lesson_code = 'L2'
Inner joins will filter the results, so you'll only get rows where both join conditions were met.
You must join the tables, group by name and put the condition in the having clause:
select s.name
from student s inner join lesson_contract l
on l.student_id = s.id
where l.lesson_code in ('L1', 'L2')
group by s.name
having count(distinct l.lesson_code) = 2
You may remove distinct if there is no case for a student to take the same lesson twice.
See the demo.
Results:
| name |
| ------- |
| Charles |
| John |

How to sum counted rows if same source id

Good Day,
I was creating a function where a user can share a post and other users may "LIKE or Comment" on it..
now on my POST table I have "id" and "source_id" + other details, to track people who like a post I created a table dedicated for like details. with columns: ID, USER_ID ( id of use who liked the post ), post_id
posts table:
id | source_id | caption
1 1 original post
2 1 share from id: 1 posts
3 3 new posts
4 4 new posts
likes table:
id | post_id | user_id
1 1 2
2 1 10
3 2 11
4 2 4
5 2 20
6 3 11
7 4 19
8 4 10
in order to count the number of like for a post, I do
SELECT a.id, a.source_id,b.num_likes
FROM posts AS a
LEFT JOIN (SELECT COUNT(user_id) AS
num_likes,post_id
FROM post_likes GROUP BY post_id ) AS b
ON b.post_id= a.id
WHERE b.num_likes != 0
result:
id | source_id | num_likes
1 1 2 <--- original post
2 1 3 <--- shared post who also got likes
3 3 1
4 4 2
what I would like to achieve is like these
id | source_id | num_likes
1 1 5
3 3 1
4 4 2
is this possible to achieve by just a query ? if so, could you please help me achieve this..
Thank you very much!
You can join the tables directly.
SELECT MIN(a.id), a.source_id, COUNT(b.num_likes) FROM posts AS a
LEFT JOIN post_likes AS b ON b.post_id= a.id
GROUP BY a.source_id
HAVING b.num_likes > 0
Might need to use a MIN for a.id since it is not aggregated. It would depend on your data and use case.
Use SUM function to get the total likes.
SELECT min(a.id) as id, a.source_id,sum(b.num_likes) as num_likes
FROM posts AS a
LEFT JOIN (SELECT count(1) AS
num_likes,post_id
FROM post_likes GROUP BY post_id ) AS b
ON b.post_id= a.id
WHERE b.num_likes != 0
GROUP BY a.source_id

Query on two tables merged with same column names

I have these tables in my MySQL database:
BUYERS
ID|SELLER
----------------
0 |Paul
1 |Jean
2 |David
3 |Jack
4 |John
5 |Fred
6 |Peter
PARIS
ID|CAR
---------
0 |Toyota
1 |BMW
2 |Honda
LONDON
ID|CAR
---------
3 |Ford
4 |BMW
5 |Honda
6 |Honda
I use the followinq query :
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
To get the following result :
ID|SELLER |CAR
----------------
0 |Paul |Toyota
1 |Jean |BMW
2 |David |Honda
3 |Jack |Ford
4 |John |BMW
5 |Fred |Honda
6 |Peter |Honda
I wanted to retrieve rows with "Honda" as "CAR" and I Tried to append the query with "Where car = 'Honda'" but without success..
Thanks for any help
Adding
WHERE car = 'Honda';
to your query only refers to the second query, i.e. the one after UNION ALL.
So either:
SELECT b.id, b.seller, p.car FROM buyers b JOIN paris p ON b.id = p.id
WHERE p.car = 'Honda'
UNION ALL
SELECT b.id, b.seller, l.car FROM buyers b JOIN london l ON b.id = l.id
WHERE p.car = 'Honda'
;
or
SELECT id, seller, car
FROM
(
SELECT b.id, b.seller, p.car FROM buyers b JOIN paris p ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car FROM buyers b JOIN london l ON b.id = l.id
) data
WHERE car = 'Honda';
Just appending WHERE car = 'Honda' is ambiguous. Which car column should be checked?
The easiest way to achieve this is to wrap your existing query within another select statement so that the query is applied on the resulting table, i.e.
SELECT * FROM
(
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
)
WHERE car = 'Honda'
Can you please try below query:
select * from (
SELECT b.id, b.seller, p.car
FROM buyers b
JOIN paris p
ON b.id = p.id
UNION ALL
SELECT b.id, b.seller, l.car
FROM buyers b
JOIN london l
ON g.id = l.id;
)
where car = 'HONDA'
This is not an answer, but mere advice.
Just in case this is your real database (I'm pretty sure it isn't), here is some advice:
The table names tell us what entities you are dealing with. In your database this is buyers, parises, and londons. You probably see your mistake ;-)
Then looking into the buyers table we see the main column is called seller. What the heck? Is it buyer or seller?
Then a column called ID should be the table's ID and uniquely identify a record in the table. You, however, are using the buyers IDs in other tables and still call them ID.
In your example each buyer has only one other record either in London or in Paris. If this is the case, then you can simply make the car a column in the buyers table instead. If you do need an n:m relation, then call the IDs by what they are, i.e. buyer_id or the like.
In any case there should be a car table containing one record per car, in order to avoid misspellings like 'Homda' in some records.
You are showing car brands, but call the table cars. If it's really about brands only, a better name would hence be brands or car_brands or the like.
Here is an example on how to design the database:
Cars
id_car | name
-------+-------
1 | BMW
2 | Ford
3 | Honda
4 | Toyota
Sellers
id_seller | name
----------+------
0 | Paul
1 | Jean
2 | David
3 | Jack
4 | John
5 | Fred
6 | Peter
Sellers_Cars
id_seller | id_car
----------+-------
0 | 1
0 | 2
0 | 4
1 | 1
2 | 3
3 | 2
4 | 1
5 | 3
6 | 3
6 | 4
A possible query:
select name as honda_seller
from sellers
where id_seller in
(
select id_seller
from sellers_cars
where car_id = (select car_id from cars where name = 'Honda')
);

mysql join query

I have two tables that I need to join. These are:
art
id | art
--------
1 | A
2 | B
3 | C
4 | D
5 | E
6 | F
7 | G
8 | H
9 | I
and
Sess
artid | sessid
--------------
1 | 1
2 | 1
3 | 1
4 | 1
1 | 2
4 | 2
5 | 2
6 | 2
1 | 3
2 | 3
7 | 3
4 | 3
where Sess.artid is a foregin key to art.id.
From the tables above we can see that there are 3 sessions: A,B,C,D, A,D,E,F and A,B,G,D.
I want to get a ranking of the arts that occur along with art A. Something like:
D=3
B=2
How could I form such a query in mysql or postgres?
You need to join twice the session table to get the article sharing the same session.
Then join one time with article for the filter clause, and another time to get the name of the other article in the other session.
SELECT aSameSession.art, count(*)
FROM art a
INNER JOIN Sess s
ON a.id = s.artid
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
INNER JOIN art aSameSession
ON sSameArticle.artid = aSameSession.id
WHERE A.art = 'A'
AND aSameSession.art <> 'A'
GROUP BY aSameSession.art
Output :
B 2
C 1
D 3
E 1
F 1
G 1
This version could be a little difficult to understand, so here a version just with the ID of the article, which is much more simple :
SELECT sSameArticle.artid, count(*)
FROM Sess s
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
WHERE s.artid = 1
AND sSameArticle.artid != 1
GROUP BY sSameArticle.artid
Output :
2 2
3 1
4 3
5 1
6 1
7 1
Adding the name of the article is just cosmetic.
Something like this, perhaps:
select art,count(*)
from sessid
left join art on art.id=artid
where sessid in (select sessid from sess where artid=1)
group by artid;
?
Example of table structure and join queries on PostgreSQL
CREATE TABLE arts (
arts_id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE sessions (
sessions_id integer NOT NULL,
arts_id integer NOT NULL REFERENCES arts
);
SELECT arts.name, count(sessions_id)
FROM arts
JOIN sessions USING (arts_id)
GROUP BY arts.name
ORDER BY count(sessions_id) DESC;
SELECT a.art, count(*) as ranking
FROM art a, sess s
WHERE a.id = s.artid
group by a.art
order by count(*) DESC;
For a statement in ANSI-92 syntax have a look at Konerak's answer.