For example, there are three rooms.
1|gold_room|1,2,3
2|silver_room|1,2,3
3|brown_room|2,4,6
4|brown_room|3
5|gold_room|4,5,6
Then, I'd like to get
gold_room|1,2,3,4,5,6
brown_room|2,3,4,6
silver_room|1,2,3
How can I achieve this?
I've tried: select * from room group by name; And it only prints the first row. And I know CONCAT() can combine two string values.
Please use below query,
select col2, GROUP_CONCAT(col3) from data group by col2;
Below is the Test case,
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ab35e8d66ffe3ac6436c17faf97ee9af
I'm not making an assumption that the lists don't have elements in common on separate rows.
First create a table of integers.
mysql> create table n (n int primary key);
mysql> insert into n values (1),(2),(3),(4),(5),(6);
You can join this to your rooms table using the FIND_IN_SET() function. Note that this cannot be optimized. It will execute N full table scans. But it does create an interim set of rows.
mysql> select * from n inner join rooms on find_in_set(n.n, rooms.csv) order by rooms.room, n.n;
+---+----+-------------+-------+
| n | id | room | csv |
+---+----+-------------+-------+
| 2 | 3 | brown_room | 2,4,6 |
| 3 | 4 | brown_room | 3 |
| 4 | 3 | brown_room | 2,4,6 |
| 6 | 3 | brown_room | 2,4,6 |
| 1 | 1 | gold_room | 1,2,3 |
| 2 | 1 | gold_room | 1,2,3 |
| 3 | 1 | gold_room | 1,2,3 |
| 4 | 5 | gold_room | 4,5,6 |
| 5 | 5 | gold_room | 4,5,6 |
| 6 | 5 | gold_room | 4,5,6 |
| 1 | 2 | silver_room | 1,2,3 |
| 2 | 2 | silver_room | 1,2,3 |
| 3 | 2 | silver_room | 1,2,3 |
+---+----+-------------+-------+
Use GROUP BY to reduce these rows to one row per room. Use GROUP_CONCAT() to put the integers together into a comma-separated list.
mysql> select room, group_concat(distinct n.n order by n.n) as csv
from n inner join rooms on find_in_set(n.n, rooms.csv) group by rooms.room
+-------------+-------------+
| room | csv |
+-------------+-------------+
| brown_room | 2,3,4,6 |
| gold_room | 1,2,3,4,5,6 |
| silver_room | 1,2,3 |
+-------------+-------------+
I think this is a lot of work, and impossible to optimize. I don't recommend it.
The problem is that you are storing comma-separated lists of numbers, and then you want to query it as if the elements in the list are discrete values. This is a problem for SQL.
It would be much better if you did not store your numbers in a comma-separated list. Store multiple rows per room, with one number per row. You can run a wider variety of queries if you do this, and it will be more flexible.
For example, the query you asked about, to produce a result with numbers in a comma-separated list is more simple, and you don't need the extra n table:
select room, group_concat(n order by n) as csv from rooms group by room
See also my answer to Is storing a delimited list in a database column really that bad?
I have problem with result when join 3 tables because I have in some place NULL a should be number or empty cell.
My tables in database:
Table nr 1: rysunek
id_rys | nazwa_rys | nazwa_klienta | ...
3 |01_116230_C0 |PHILIPS
7 |11_002177_A0 |P&G
20 |01_101854_B0 |MARS FOOD
333 |None |None
( + 7 columns which do not use in this query)
Table nr 2: artykul
id_art |id_rys |nazwa_art | id_status | ...
1 |3 |00_16_1234 | 1
2 |7 |00_16_1235 | 3
3 |7 |00_16_1236 | 0
4 |333 |00_16_1237 | 0
( + 10 columns which do not use in this query)
Table nr 3: statusy
id_status |kod_status
1 |IA
2 |NC
3 |861
Mysql query looks like this:
SELECT r.nazwa_klienta
, r.nazwa_rys
, a.nazwa_art
, s.kod_status
FROM artykul a
LEFT
JOIN rysunek r
ON a.id_rys = r.id_rys
LEFT
JOIN statusy s
ON a.id_status = s.id_status;
And result looks like this:
nazwa_klienta | nazwa_rys | nazwa_art | kod_status
NULL | NULL | 00_16_1234 | IA
NULL | NULL | 00_16_1235 | 861
P&G | 11_002177_A0 | 00_16_1236 | NULL
None | None | 00_16_1237 | NULL
I need to the result of query above look like this:
nazwa_klienta | nazwa_rys | nazwa_art | kod_status
PHILIPS | 01_116230_C0 | 00_16_1234 | IA
P&G | 11_002177_A0 | 00_16_1235 | 861
P&G | 11_002177_A0 | 00_16_1236 | [empty cell]
None | None | 00_16_1237 | [empty cell]
How should looks like my query? I tried all join methods but none of them work.
Maybe I should change structure of my tables? I'm waiting for some suggestion from somebody... :)
Left joins are going to create empty entries for your rysunek columns whenever there is no row in that table that matches artykul's. If you don't want them listed, then don't use an outer join between those two tables (I note you didn't list them in your desired output).
For the other NULLs, from kod_status, since it is a numeric column, pretty much your choices are: take the null; or turn it into a 0 with a COALESCE(kod_status,0), or cast the result to a string and turn its nulls into empty strings. There are command-line options in the mysql command-line tool (which your output appears to be from) (see http://dev.mysql.com/doc/refman/5.7/en/mysql-commands.html ) there may be a way to change how it outputs nulls if that would fit your use-model needs.
I have a rather simple (I think) question at hand. The example tables and the result I need are provided below (in reality those tables containt much more columns and data, I jest left what is relevant). There is also the query which returns exactly what I need. However, I dont like rather crude way in which it works (I dont like subqueries in general). The question is, how can I rewrite the query so it will automatically react to more columns appearing in TABLE2 in the future? Right now if the "z" column would be added to TABLE2, I need to modify each query in the code and add one more relevant subquery. I just want the select to read the entire content of TABLE2 and translate the id numbers to corresponding strings from TABLE1.
TABLE1
-----------------
id |x |
-----------------
567 |AAA |
345 |BBB |
341 |CCC |
827 |DDD |
632 |EEE |
503 |FFF |
945 |GGG |
234 |HHH |
764 |III |
123 |JJJ |
-----------------
TABLE2
-------------------------
id |x |y |
-------------------------
1 |123 |341 |
2 |567 |632 |
3 |345 |945 |
4 |764 |503 |
5 |234 |827 |
-------------------------
THE RESULT I NEED
-----------------
A |B |
-----------------
JJJ |CCC |
AAA |EEE |
BBB |GGG |
III |FFF |
HHH |DDD |
-----------------
The query I have
SELECT
(SELECT `x` FROM `TABLE1` WHERE `TABLE2`.`x` LIKE `TABLE1`.`id` LIMIT 1) as A,
(SELECT `x` FROM `TABLE1` WHERE `TABLE2`.`y` LIKE `TABLE1`.`id` LIMIT 1) as B
FROM `TABLE2` ORDER BY `id` DESC;
You might want to restructure your data model:
Instead of:
-------------------------
id |x |y |
-------------------------
1 |123 |341 |
2 |567 |632 |
3 |345 |945 |
4 |764 |503 |
5 |234 |827 |
-------------------------
You would have:
----------------------
col_id |col |
----------------------
1 |x |
2 |y |
----------------------
---------------------------
id |col_id |col_val |
---------------------------
1 |1 |123 |
1 |2 |341 |
2 |1 |567 |
2 |2 |632 |
etc
---------------------------
Probably not worth the hassle (you would effectively need to pivot when you're accessing multiple columns at a time) but it would allow you to do the query that you want across all current and future columns.
You can't do that with a plain select.
What you can do is creating a view with the translated values. You still have to modify the view when the original table is changed but your queries don't have to.
You can use dynamic sql statements, but still you can use the dynamic statements only if you are sure that table 2 will have the columns of same type like x and y(Apart from id).
Let me know if you are not sure how to write it.
All the best.
I'm having trouble combining tables that have a one-to-many mapping using LEFT JOIN and GROUP BY.
I have the following table with a unique ID (in the illustrative example this is house_number)
Houses:
|house_number| bedrooms|
|0 | 4 |
|1 | 3 |
|2 | 1 |
And I want to LEFT JOIN with a second table USING the unique ID, where the second table may or may not have multiple entries per unique ID. E.g,
Occupants:
| house_number | occupant_id | type |
| 0 | 3 | 19 |
| 0 | 1 | 20 |
| 0 | 2 | 21 |
| 2 | 7 | 20 |
Now what I want to achieve is exactly ONE entry per house number, but giving a preference in the LEFT JOIN to occupants with a type of 20, whilst also keeping those houses which do not have any occupants listed, e.g,
|house_number| bedrooms| occupant_id | type |
|0 | 4 | 1 | 20 |
|1 | 3 | null | null |
|2 | 1 | 7 | 20 |
I can use a GROUP BY to achieve only one entry per house, however, I need to ensure that the occupant row returned with it (if it exists) has type = 20.
If I simply use a WHERE (type = 20), then I wouldn't get an entry returned for house_number = 1.
How would I achieve this final table?
What about trying WHERE (type = 20 OR type is null) condition instead?
SELECT h.house_number,h.bedrooms
, o.occupant_id,o.ztype
FROM houses h
LEFT JOIN occupants o ON h.house_number = o.house_number
AND o.ztype =20
;
BTW I had to replace "type" by "ztype" because type is a reserved word in Postgres.
I'm working on mysql and have two tables with the same schema:
preTrial
|id|accusedId|articleid|
------------------------
|1 | 1 | 1 |
|2 | 1 | 2 |
|3 | 1 | 3 |
|4 | 2 | 1 |
|5 | 2 | 2 |
trial
|id|accusedId|articleid|
------------------------
|1 | 1 | 1 |
|2 | 1 | 2 |
|3 | 2 | 1 |
|4 | 2 | 2 |
I want to get those accusedIds where all the articleIds of the first and the second tables are equal.
The above example should only return the accusedId 2, cause for accusedId 1 there is no articleId 3 in the second table.
I hope you understand what i mean. I'm currently writing my thesis in law, and the the time i was into sql is long gone by. Of course i already did some research, and tried several joins, but i was not able to find a solution. Hopefully you can help me.
Try something like this:
select a.accusedId , sum(a.accusedid) as cnt_a, sum(coalesce(b.accusedId, 0)) as cnt_b
from a left join b on a.accusedId = b.accusedId and a.articleId = b.articleId
group by accusedId
having cnt_a = cnt_b
I haven't even run that, so it might be a little off, but give it a lash. What it's doing is returning zeroes for a row in a not matched by b, so the HAVING clause will filter your grouped results to those where the article counts are equal.