Combine two tables into one table - mysql

I need to join user table with all user images in one row, like this
table user
+----+---------------+
|id | name |
+----+---------------+
| 1 | Mike |
| 2 | Jerry |
| .. | ..... |
+----+---------------+
table image
+------+---------+---------+
| id | user_id | img |
+------+---------+---------+
| 1 | 1 | img_1 |
| 2 | 1 | img_2 |
| 3 | 1 | img_3 |
| 4 | 2 | img_4 |
| .. | .... | ..... |
+------+---------+---------+
I need to generate SQL results like this
+------+--------+----------+----------+----------+
| id | name | img1 | img2 | img3 |
+------+--------+----------+----------+----------+
| 1 | Mike | img_1 | img_2 | img_3 |
+------+--------+----------+----------+----------+
| ... | .... | .... | .... | .... |
+------+--------+----------+----------+----------+

That's not natively supported in mysql, however you could use a pivot to create exactly your result, however that requires some hardcoding I'd avoid if possible.
A simple solution for your task could be using GROUP_CONCAT(), which would produce a resultset like
+------+--------+----------+----------+----------+
| id | name | images |
+------+--------+----------+----------+----------+
| 1 | Mike | img_1;img_2;img_3 |
+------+--------+----------+----------+----------+
| ... | .... | |
+------+--------+----------+----------+----------+
If that's good enough, you can achieve that with
SELECT a.id, a.name, GROUP_CONCAT(b.img) images
FROM user a
INNER JOIN image b ON a.id = b.user_id
GROUP BY b.user_id;

Related

How do I query a three-level structure in two joined tables?

There are two tables,
Table A has a three-level structure that looks like
| id | name | level | up_level_id |
| :------- | :-------: | :------: | ----------:|
| 1 | lv1_name1 | 1 | null |
| 2 | lv1_name2 | 1 | null |
| 3 | lv2_name1 | 2 | 1 |
| 4 | lv2_name2 | 2 | 2 |
| 5 | lv3_name1 | 3 | 3 |
| 6 | lv3_name2 | 3 | 3 |
| 7 | lv3_name3 | 3 | 4 |
| 8 | lv3_name4 | 3 | 4 |
Table B looks like
| amount | org_id |
| -------- | -------- |
| 12,000 | 5 |
| 15,000 | 6 |
| 20,000 | 7 |
| 18,000 | 8 |
Table A and Table B can be joined on A.id=B.org_id, but they are all at the level-3 of Table A(Only level-3 has their amount)
I want to query the top-level name,level-1 name, and the summary amount that looks like
| sum_amount | top_lvl_name |
| -------- | -------- |
| 27,000 | lv1_name1 |
| 38,000 | lv1_name2 |
For Testing, I have already accomplished the query of the level-1 name from the level-3 id in TableA
The SQL is as follows
SELECT name
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id IN (
SELECT up_level_id
FROM Table A
WHERE id=5) --query the id:5's top-level name
);
But when I join these two tables as follows, it goes wrong
SELECT sum(amount) AS sum_amount, name AS top_lvl_name
FROM TableA, TableB
WHERE id = org_id
AND id IN (
SELECT up_level_id
FROM TableA
WHERE id IN (
SELECT up_level_id
FROM TableA
WHERE TableA.id IN(
SELECT org_id
FROM TABLEB
)
)
);
I get nothing as above
What can I do to make this query to be correct?
Thanks for everyone's answer and comment.
Finally, I find it very difficult to query the result as I wish. So, I've come up with a shortcut——create a new table that a three-level structure recorded horizontally, which looks like
| lv1_id | lv2_name | lv2_id | lv2_name | lv3_id | lv3_name |
| :------- | :-------: | :------: | :----------:| :------: | :----------:|
| 1 | lv1_name1 | 3 | lv2_name1 | 5 | lv3_name1 |
| 1 | lv1_name1 | 3 | lv2_name1 | 6 | lv3_name2 |
| 2 | lv1_name2 | 4 | lv2_name1 | 7 | lv3_name3 |
| 2 | lv1_name2 | 4 | lv2_name1 | 8 | lv3_name4 |
As above,I can easily connect two tables

MYSQL JOIN two tables based on a relation in third table and concat the data from the second table

here's the situation, I have tables as follows:
App table
+--------+------------+--+
| AppID | AppName | |
+--------+------------+--+
| 1 | App1 | |
| 2 | App2 | |
| 3 | App3 | |
+--------+------------+--+
Tags Table
+--------+------------+--+
| TagID | TagName | |
+--------+------------+--+
| 10 | Tag1 | |
| 20 | Tag2 | |
| 33 | Tag3 | |
+--------+------------+--+
AppTags Table
+--------+----------+--+
| AppID | TagID | |
+--------+----------+--+
| 1 | 20 | |
| 1 | 30 | |
| 2 | 10 | |
| 2 | 30 | |
| 3 | 10 | |
| 3 | 20 | |
+--------+----------+--+
I'm looking for a result like this:
+----------+---------------+--+
| AppName | Tags | |
+----------+---------------+--+
| App1 | Tag2, Tag3 | |
| App2 | Tag1, Tag3 | |
| App3 | Tag1, Tag2 | |
+----------+---------------+--+
I tried to use GROUP_CONCAT but I didn't know how to make a full query with a WHERE clause in it so I can define which data I want. I also of course tried to use JOIN but I was getting each TagName in a separate row with it's AppName.
Thank you.
SELECT AppName, GROUP_CONCAT(TagName) Tags
FROM AppTags
NATURAL JOIN App
NATURAL JOIN Tags
GROUP BY AppName;

Query equivalent to two group by's without a subquery?

I'm trying to run a report on User ACL's. We use MYSQL and my we're prohibited from using subqueries for performance reasons. The goal is to turn this:
--------------------------------
| userName | folderID | roleID |
--------------------------------
| gronk | 1 | 1 |
| gronk | 2 | 2 |
| gronk | 4 | 2 |
| tbrady | 1 | 2 |
| jedelman | 1 | 1 |
| jedelman | 2 | 1 |
| mbutler | 1 | 2 |
| mbutler | 2 | 2 |
| bill | 1 | 3 |
| bill | 2 | 3 |
| bill | 3 | 3 |
| bill | 4 | 3 |
--------------------------------
Into this:
------------------------
| Lowest Role | Number |
------------------------
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
------------------------
I can see how to do it with a subquery. The inner query would do a group by on userName with a min(roleID). Then the outer query would do a group by on the lowest role and count(*). But I can't see how to do it without a subquery.
Also, if it helps I created a SQL Fiddle that has the data above.
I found a solution using a left join:
select UFM.roleID, count(distinct UFM.userName)
from UserFolderMembership UFM
left join UserFolderMembership UFM2 on
UFM.userName = UFM2.userName and
UFM.roleID > UFM2.roleID
where
UFM2.userName is null
group by
UFM.roleID

A simple many to many SQL example

I'm trying to figure out a good way of doing an SQL query that returns a table of user names and their choices (there are a set number of choices and a user can have many choices) as in the example below. I haven't been able to find a good simple example of this (other than how the relationship is laid out). Is this solution viable or is there a better way of doing it? I seem to get the table I'm looking for.
SELECT
users.name,
choices.choice as choice
FROM
choice
JOIN relation ON choice.choice_id = relation.choice_id
JOIN users ON users.name_id = relation.user_id;
Gives me the correct table:
+------+--------+
| name | choice |
+------+--------+
| amy | a |
| amy | b |
| amy | c |
| joe | d |
+------+--------+
The simple database looks like this:
Users
+------+---------+
| name | name_id |
+------+---------+
| amy | 1 |
| joe | 2 |
+------+---------+
Choices
+----------+---------+
| choice_id| choice |
+----------+---------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
+----------+---------+
Relation
+----------+---------+
| choice_id| user_id |
+----------+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
+----------+---------+

What is the correct way of getting data from a MySQL table based on columns from another? Transposing?

I have a table like this:
idstable
+--------+-----+-----+-----+-----+-----+
| userid | id1 | id2 | id3 | id4 | id5 |
+--------+-----+-----+-----+-----+-----+
| 1 | 6 | 2 | 52 | 32 | 16 |
+--------+-----+-----+-----+-----+-----+
| 2 | 12 | 5 | 18 | 21 | 5 |
+--------+-----+-----+-----+-----+-----+
| ... | ... | ... | ... | ... | ... |
which i want to get the id numbers stored in the columns and get rows from another table with them. The table i wish to get the rows from is:
namestable
+----+----------+
| id | name |
+----+----------+
| 6 | Bruce |
+----+----------+
| 2 | Mary |
+----+----------+
| 52 | Dick |
+----+----------+
| 32 | Bob |
+----+----------+
| 16 | Jack |
+----+----------+
| .. | ... |
The result-set i'm im trying to get is something like:
+------+----+-------+
| User | id | name |
+------+----+-------+
| 1 | 6 | Bruce |
+------+----+-------+
| 1 | 2 | Mary |
+------+----+-------+
| 1 | 52 | Dick |
+------+----+-------+
| 1 | 32 | Bob |
+------+----+-------+
| 1 | 16 | Jack |
+------+----+-------+
How can i query the idstable with a userid to retrieve the ids associated with it, to then retrieve the correct rows from the namestable? I've read this is called transposing but i've yet to find a concise example.
Any ideas?
join
SELECT idstable.id as User, namestable.id as id, namestable.name as name
FROM idstable it
JOIN namestable nt on (nt.id = it.id1 or nt.id = it.id2 ... 3,4,5 like the first two)
Ideally, your idstable wouldn't have 5 columns, but 5 rows per per id.