MySQL, select multiple rows as one based on foreign key - mysql

i have the following 2 tables.
| ID | NAME | AGE |
|----|------|-----|
| 0 | John | 30 |
| 1 | Nick | 35 |
| 2 | Mike | 30 |
| USERID | FRUIT |
|--------|------------|
| 0 | apple |
| 0 | orange |
| 1 | banana |
| 1 | tomato |
| 1 | grape |
| 1 | watermelon |
| 2 | pear |
| 2 | cherry |
I'm using this query in order to get what fruit every user with age<34 likes.
SELECT users.name, fruit FROM users,fruits WHERE users.id=fruits.userid AND users.age<34;
Result:
| NAME | FRUIT |
|------|--------|
| John | apple |
| John | orange |
| Mike | pear |
| Mike | cherry |
sqlfiddle
Is there a way to have only one row returned for every user with the fruits on one or multiple columns?
Desired result:
| NAME | FRUIT |
|------|---------------|
| John | apple,orange |
| Mike | pear,cherry |
or
| NAME | FRUIT | FRUIT |
|------|--------|--------|
| John | apple | orange |
| Mike | pear | cherry |
I tried using GROUP_CONCAT() but i didn't get the result i expected, any help would be great.
Thanks in advance for your time.

SELECT users.name, group_concat( fruit )
FROM users,fruits
WHERE users.id=fruits.userid AND users.age<34
group by user.name

Try This(The STUFF function):
CREATE TABLE #Test(
Name VARCHAR(100),
FRUIT VARCHAR(100)
)
INSERT INTO #Test VALUES
('John', 'apple'),
('John', 'orange'),
('Mike', 'pear'),
('Mike', 'cherry')
SELECT Name,
STUFF((SELECT ', ' + FRUIT
FROM #Test t1
WHERE t1.Name = t2.Name
FOR XML PATH(''), TYPE).value('.','VARCHAR(MAX)'),1,2,'') AS 'Fruits'
FROM #Test t2
Group by Name
Drop Table #Test
This outputs:
Name Fruits
John apple, orange
Mike pear, cherry

Related

Finding MySQL near-duplicates across two columns using wildcards

I have a table with id, first_name and last_name columns. I'd like to get a listing of rows where last_name and the first character of first_name are duplicated. I am groping my way around and have a sense that there is a COUNT('WHERE') in there, but can't quite get to it.
In essence, I'm looking for possible duplicates. So, from this subset:
+------+-----------+-----------+-------------+------------+
| id | firstName | lastName | dateOfBirth | createdOn |
+------+-----------+-----------+-------------+------------+
| 143 | Susie | Wong | 2015-12-01 | 2016-07-11 |
| 1268 | Dale | Armstrong | 2017-01-01 | 2017-01-04 |
| 1435 | Olive | Armstrong | 1941-03-11 | 2017-03-08 |
| 2013 | Timotini | Attilio | 1932-01-01 | 2017-08-21 |
| 2014 | Olinda | Attilio | 1938-01-01 | 2017-08-21 |
| 3076 | Sue | Armstrong | 1951-06-01 | 2018-06-22 |
| 3079 | Susan | Armstrong | 1951-09-15 | 2018-06-22 |
+------+-----------+-----------+-------------+------------+
I would like a query that returns only 3076 and 3079 (Sue and Susan Armstrong) based on looking for a matching last name and a matching first initial, like so:
+------+-----------+-----------+-------------+------------+
| id | firstName | lastName | dateOfBirth | createdOn |
+------+-----------+-----------+-------------+------------+
| 3076 | Sue | Armstrong | 1951-06-01 | 2018-06-22 |
| 3079 | Susan | Armstrong | 1951-09-15 | 2018-06-22 |
+------+-----------+-----------+-------------+------------+
Here's one option using exists and left:
select *
from yourtable y
where exists (
select 1
from yourtable y2
where y.id != y2.id
and y.lastname = y2.lastname
and left(y.firstname,1) = left(y2.firstname,1)
)
Sample Fiddle Demo
Duplicates of last_name
SELECT id, first_name, last_name, COUNT(*) c
FROM table
GROUP BY last_name
HAVING c > 1;
For grouping by the first character in first_name, try playing with left() function

How select remaining unspecified columns

I am looking to overwrite a column name in a table with an existing column name.
I am Looking for a way to get the remaining unspecified columns in the tables.
Note:
The query could have more joins in the future.
eg
Person
+-----------+----------+---------+
| firstname | lastname | pers_id |
+-----------+----------+---------+
| Joe | Soap | 1 |
| Bobby | Pin | 2 |
| Janet | Jackson | 3 |
+-----------+----------+---------+
Category
+----------+-------------------+--------+
| type | description | cat_id |
+----------+-------------------+--------+
| customer | people who pay us | 1 |
| employee | people we pay | 2 |
| director | people who direct | 3 |
+----------+-------------------+--------+
Person_Cat
(=^ェ^=)
+---------+--------+
| pers_id | cat_id |
+---------+--------+
| 3 | 1 |
| 2 | 2 |
| 1 | 3 |
+---------+--------+
Query
SELECT *, CONCAT(p.firstname, ' '
, p.lastname) as full_name
, c.cat_id AS category_id
, p.pers_id AS cat_id
FROM Person AS p
JOIN Person_Cat AS pc ON(p.pers_id = pc.pers_id)
JOIN Category AS c ON (pc.cat_id = c.cat_id)
OUTPUT
(Apologies for the length but the table after is more important)
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| p | p | p | pc | pc | c | c | c | Select | Select | Select |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| firstname | lastname | pers_id | pers_id | cat_id | type | description | cat_id | full_name | category_id | cat_id |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| Janet | Jackson | 3 | 3 | 1 | customer | people who pay us | 1 | Janet jackson | 1 | 3 |
| Bobby | Pin | 2 | 2 | 2 | employee | people who we pay | 2 | Bobby Pin | 2 | 2 |
| Joe | Soap | 1 | 1 | 3 | director | people who direct | 3 | Joe Soap | 3 | 1 |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
The headers above column names are there for reference
to where they comes from.
Column summary -
firstname, lastname, pers_id, pers_id, cat_id, type,
description, cat_id, full_name ,category_id, cat_id
Wanted output
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| p | p | pc | pc | c | c | Select | Select | Select |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| firstname | lastname | pers_id | cat_id | type | description | full_name | category_id | cat_id |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| Janet | Jackson | 3 | 1 | customer | people who pay us | Janet jackson | 1 | 3 |
| Bobby | Pin | 2 | 2 | employee | people who we pay | Bobby Pin | 2 | 2 |
| Joe | Soap | 1 | 3 | director | people who direct | Joe Soap | 3 | 1 |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
Column summary -
firstname, lastname, pers_id, cat_id, type,
description, full_name ,category_id, cat_id
Notice:
The p.pers_id and the c.cat_id are not present. I would like to think this would be because the were called directly and unmodified unlike the first and lastname used in ConCat
When the short answer is that there is no such concept as Select [remaining columns]at this time (2015-06-17), if you want to use SELECT * but only remove redundant columns,
then you will need to explicitly remove (ignore) those redundant columns when rendering your view.
You will have to explicitly configure logic of which columns to ignore, which is pretty much the same thing as explicitly listing the columns that you are interested in, so you get back to the argument against selecting all columns that I made in the comments above.
Unless your table schema is changing all the time, there really isn't reason for this.

Counting the number of times something appears in a column and recording it

So in order to know how many people in a table are called Johnny I would need to excecute the following query.
Query:
Select count(*) from mytable where first = 'Johnny';
It would give me 2 as the result.
What I wish to do however is record this number in the count column so that the end result comes out like this.
+--------+----------+
| First | COUNT |
+--------+----------+
| Johnny | 2 |
| Diane | 1 |
| Johnny | 2 |
| Harold | 1 |
| Amy | 3 |
| Roy | 2 |
| Amy | 3 |
| Amy | 3 |
| Roy | 2 |
+--------+----------+
Is there any query or procedure capable of resulting in this type of output?
To get your exact output, you need to use a subquery:
select
mytable.First,
counts.`COUNT`
from
mytable
join (
select
First,
count(*) `COUNT`
from
mytable
group by
First
) counts on mytable.First = counts.First;
Try this:
SELECT T1.First, T2.COUNT
FROM mytable T1 JOIN
(SELECT First, COUNT(*) as COUNT
FROM mytable
GROUP BY First) as T2 ON T1.First=T2.First
The result will be:
+--------+----------+
| First | COUNT |
+--------+----------+
| Johnny | 2 |
| Diane | 1 |
| Johnny | 2 |
| Harold | 1 |
| Amy | 3 |
| Roy | 2 |
| Amy | 3 |
| Amy | 3 |
| Roy | 2 |
+--------+----------+

MySQL query DISTINCT, COUNT

I'm trying to use a SELECT DISTINCT to find out how many people have cars, how many have boats, now many bikes and so on, from this table
| name | obj |
---------------------
| john | car |
| mary | boat |
| dave | car |
| james | bike |
| steve | car |
| walt | bike |
ex: bike - 2
You can use this query
SELECT obj, COUNT(name) as nb FROM table GROUP BY obj ORDER BY obj
Result (sqlfiddle):
| obj | nb |
---------------------
| bike | 2 |
| boat | 1 |
| car | 3 |
select sum(obj = 'car') as car_count,
sum(obj = 'boat') as boat_count
from your_table

Mysql query to select only one unique name on a criteria

I have a table like this.
+------------+-------------+--------------+
| name | hobby | hobby_number |
+------------+-------------+--------------+
| jack | sport | 1 |
| marco | skydiving | 3 |
| alfonso | driving | 1 |
| marco | learning | 2 |
| jack | dancing | 2 |
+------------+-------------+--------------+
I want to use sql select statement to select only one unique name.
The table I want may look like this:
+------------+-------------+--------------+
| name | hobby | hobby_number |
+------------+-------------+--------------+
| jack | sport | 1 |
| marco | learning | 2 |
| alfonso | driving | 1 |
+------------+-------------+--------------+
What should sql query be?
Thank you in advance.
select t.* from your_table t
inner join
(
select name, min(hobby_number) as minh
from your_table
group by name
) x on x.name = t.name and x.minh = t.hobby_number