Use MySQL to create a string out of a subquery? - mysql

What I'm hoping to do is create a string out of a table WITHIN a query so that I may be able to place that string in another query I'm creating. Say, I have this for a table:
index | position | name
----------------------------------------
1 | member | John Smith
2 | chair | Mary Jones
3 | member | Mary Jones
4 | contact | Grace Adams
5 | director | Grace Adams
6 | member | Grace Adams
7 | treasurer | Bill McDonnell
8 | vice chair | Bill McDonnell
9 | member | Ishmael Rodriguez
I'm looking for the result as follows:
name | positions
----------------------------------------
John Smith | member
Mary Jones | chair,member
Grace Adams | contact,director,member
Bill McDonnell | treasurer,vice chair
Ishmael Rodriguez | member
I was hoping I could use some variant of CONCAT_WS() to get my result, like this...
SELECT
a.NAME,
CONCAT_WS(
',',
(
SELECT
position
FROM
TABLE
WHERE
NAME = a.NAME
)
)AS positions FROM ---------------
Obviously, this isn't working out for me. Any ideas?

Use GROUP_CONCAT[docs]
SELECT name, GROUP_CONCAT(position) result
FROM tableName
GROUP BY name
ORDER BY `index`
SQLFiddle Demo

Use GROUP_CONCAT like so:
SELECT name, GROUP_CONCAT(position SEPARATOR ',')
FROM Table
GROUP BY name

Related

How to select a column's value, only if all other entries with the same value exist and match? (MYSQL)

The title is a bit messy, but here's an example
suppose we have table:
| name | room |
=================
| John | 4 |
| John | 6 |
| John | 9 |
| Smith | 4 |
| Smith | 6 |
| Brian | 4 |
| Brian | 6 |
| Brian | 9 |
I want to select John and Brian because they both have exactly rooms 4, 6 and 9, but not Smith, since he doesn't have the room 9. (If we had another person who ONLY has room 4 and 6, then it'd select that other person as well as Smith).
I know I need to do some kind of correlated query, but I'm not sure how to actually get it to do something like
for a check for b
If you want groups of names that share the exact same rooms, I would recommend group_concat():
select rooms, group_concat(name) as names
from (select name, group_concat(room order by room) as rooms
from t
group by name
) n
group by rooms;
If you want only combinations with more than one name, then add having count(*) > 1 to the outer select.

How to count unique items in column in Access

I need help. I can't seem to find the logic behind this code.
I am working on a voting system, and I need to output the results of the votes.
I want to count all of the rows that has a unique name in it and output how many.
My table goes like this.
voterid | pres | vpres | sec | trea | PIO
---------------------------------------------
1 | John | Mitch | James | Jack | Eman
2 | John | Pao | Bryan | Jack | Faye
3 | Kelvin | Pao | James | Jeck | Faye
Output should be
Pres | Votes
--------------
John | 2
Kelvin | 1
Here's my code.
SELECT DISTINCT
pres,
(SELECT COUNT(pres) FROM (SELECT DISTINCT pres FROM tblVote AS Votes)) AS Votes
FROM tblVote
Thanks in advance!
I think you are just looking for a simple GROUP BY query:
SELECT pres, COUNT(*) AS Votes
FROM tblVote
GROUP BY pres

MySQL innerjoin on an array field

i have 2 tables
[series]
--------------
ID | ART
--------------
1 | sculptor
2 | painter
3 | writer
-----------
[artists]
--------------
NAME | ART_IDs
--------------
john | 1
jack | 1,2
jill | 2,1
jeff | 3,1
which I want to join like this:
SELECT se.art, ar.name as artist
FROM series AS se
JOIN artists AS ar ON FIND_IN_SET(se.id , ar.art_ids) > 0
What I get is only the first values:
[result]
-------------------
ART | ARTISTS
-------------------
sculptor | john
sculptor | jack
painter | jill
writer | jeff
Instead of:
[result]
----------------------------
ART | ARTISTS
----------------------------
sculptor | john
sculptor,painter | jack
painter,sculptor | jill
writer,sculptor | jeff
Try this:
SELECT GROUP_CONCAT(se.art ORDER BY FIND_IN_SET(se.id , ar.art_ids)) as art, ar.name as artist
FROM series AS se
JOIN artists AS ar ON FIND_IN_SET(se.id , ar.art_ids) > 0
GROUP BY ar.name
If you want to concat column in each group, GROUP_CONCAT can help you.
Check demo in Rextester.

Combining multiple rows into a comma delimited list in SQL

I have a MySQL table StudentName(id,name) that looks like this:
id | name
++++++++
1 | alex
1 | adam
1 | adnan
2 | ben
2 | bush
3 | cris
4 | daisi
4 | diana
And I'd like to make a new table like this:
id | name
+++++++++++
1 | alex, adam, adnan
2 | ben, bush
3 | cris
4 | daisi, diana
Is there a way to accomplish this?
The group_concat function is what you're looking for:
SELECT id, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ')
FROM my_table
GROUP BY id

Tricky SQL query involving consecutive values

I need to perform a relatively easy to explain but (given my somewhat limited skills) hard to write SQL query.
Assume we have a table similar to this one:
exam_no | name | surname | result | date
---------+------+---------+--------+------------
1 | John | Doe | PASS | 2012-01-01
1 | Ryan | Smith | FAIL | 2012-01-02 <--
1 | Ann | Evans | PASS | 2012-01-03
1 | Mary | Lee | FAIL | 2012-01-04
... | ... | ... | ... | ...
2 | John | Doe | FAIL | 2012-02-01 <--
2 | Ryan | Smith | FAIL | 2012-02-02
2 | Ann | Evans | FAIL | 2012-02-03
2 | Mary | Lee | PASS | 2012-02-04
... | ... | ... | ... | ...
3 | John | Doe | FAIL | 2012-03-01
3 | Ryan | Smith | FAIL | 2012-03-02
3 | Ann | Evans | PASS | 2012-03-03
3 | Mary | Lee | FAIL | 2012-03-04 <--
Note that exam_no and date aren't necessarily related as one might expect from the kind of example I chose.
Now, the query that I need to do is as follows:
From the latest exam (exam_no = 3) find all the students that have failed (John Doe, Ryan Smith and Mary Lee).
For each of these students find the date of the first of the batch of consecutively failing exams. Another way to put it would be: for each of these students find the date of the first failing exam that comes after their last passing exam. (Look at the arrows in the table).
The resulting table should be something like this:
name | surname | date_since_failing
------+---------+--------------------
John | Doe | 2012-02-01
Ryan | Smith | 2012-01-02
Mary | Lee | 2012-03-04
How can I perform such a query?
Thank you for your time.
You can take advantage of the fact that if someone passed the most recent exam, then they have not failed any exams since their most recent pass: therefore the problem reduces to finding the first exam failed since the most recent pass:
SELECT name, surname, MIN(date) date_since_fail
FROM results NATURAL LEFT JOIN (
SELECT name, surname, MAX(date) lastpass
FROM results
WHERE result = 'PASS'
GROUP BY name, surname
) t
WHERE result = 'FAIL' AND date > IFNULL(lastpass,0)
GROUP BY name, surname
See it on sqlfiddle.
I should use a subquery that fetch last passed exam,
somthing like:
SET #query_exam_no = 3;
SELECT
name,
surname,
MIN(IF(date > last_passed_exam, date, NULL)) AS date_failing_since
FROM
exam_results
LEFT JOIN (
SELECT
name,
surname,
MAX(date) AS last_passed_exam
FROM exam_results
WHERE result = 'PASS'
GROUP BY name, surname
) AS last_passed_exams USING (name, surname)
HAVING
MAX(IF(exam_no = #query_exam_no, result, NULL)) = 'FAIL'
GROUP BY name, surname
This is enough:
select t.name,
t.surname,
t.date as 'date_since_failing'
from tablename t
inner join
(
select name,
surname,
max(exam_no) as exam_no
from tablename
group by name, surname
having min(result) = 'FAIL'
) aux on t.name = aux.name and t.surname = aux.surname and t.exam_no = aux.exam_no
The condition you are asking for is good for nothing you can do it without it. Here is the working example.
select
e.name,
e.sur_name,
min(e.date) as `LastFailed`
from exams as e
where e.result = 'Fail'
group by e.name
order by e.name
This produces this result
name sur_name LastFailed
Ann Evans 2012-02-03
John Doe 2012-02-01
Mary Lee 2012-01-04
Ryan Smith 2012-01-02