Select a record n times which n = times of occurrences - mysql

I want to select a record n times in which n is the number of times a string has occurred in a field.
Example:
mytable:
+--------+------------------------------------+
| id | content |
+--------+------------------------------------+
| 1 | This string contains two strings. |
| 2 | This is a string. |
| 3 | This does not contain our keyword. |
+--------+------------------------------------+
Now I want the result of such a hypothetical query to be like the following result:
/* hypothetical: this won't yield the desired result obviously */
SELECT * FROM mytable WHERE content LIKE "%string%";
+--------+------------------------------------+
| id | content |
+--------+------------------------------------+
| 1 | This string contains two strings. |
| 1 | This string contains two strings. |
| 2 | This is a string. |
+--------+------------------------------------+
Is this even possible?
Thanks

Related

How can I merge two strings of comma-separated numbers in MySQL?

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?

SQL - Select column with certain value in it and other random values

Let me say i have a table called test with the following data
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 2 | 355488020906457 |
| 3 | 864296100098739 |
| 4 | 864296100098325 |
| 5 | 864296100119956 |
What i want to do is to be able to write a select statement that returns a 3 rows with two random values and one mandatory value from the t_number column
for example if the mandatory value is 864291100247345 the output should something like below
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 2 | 355488020906457 |
| 4 | 864296100098325 |
OR
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 3 | 864296100098739 |
| 4 | 864296100098325 |
I have tried the below query but it's not yielding the output i expect, in a sense that it does return a result but without the mandatory value
SELECT * FROM test WHERE t_number = 864291100247345 OR id LIMIT 3;
What is the best way to go about this?
Thank you.
You can use order by:
SELECT t.*
FROM test
ORDER BY (t_number = 864291100247345) DESC,
rand()
LIMIT 3;
This returns the mandatory number first and then random numbers after that.
MySQL treats boolean values (the result of the = expression) as numbers in a numeric context, with "1" for true and "0" for false. So the first expression in the order by sorts the result set with the "true" conditions first, followed by the others.

MariaDB 10.1 JsonGet_string

In one of our columns we store this example json string:
[{"Name":"Pay Amount","Value":"0.00"},{"Name":"Period","Value":"3"},{"Name":"Client","Value":"TestClient"},{"Name":"Our Reference","Value":""},{"Name":"Pay Type","Value":"Test"}]
We repeat the Names through out and the values will differ.
I've tried querying this data using JsonGet_string :
SELECT
JSONGET_string(Header, "Name") Name
FROM tbl
but what it does it selects the first one i.e PayAmount and it only displays a list of payamount it doesn't select anything for Period, Client etc.
The result that it returns looks like this:
| Name |
|----------|
| |
| PayAmount|
| PayAmount|
And it should return this:
| Name |
|-------------|
| |
| PayAmount |
| Period |
| Client |
| OutReference|
| Pay Type |
Any ideas?

Mysql concatenate only specific rows

In Mysql, I have the following table:
id | paramname | paramcategory | value |
---+-------------+-------------------+-----------------+
1 | width | dimensions | 240 |
2 | height | dimensions | 400 |
3 | param1 | category1 | some value 1 |
4 | param2 | category1 | some value 2 |
5 | param3 | category10 | some value 100 |
...
I'd like to have a query that will return a table with only several rows concatenated, and all other rows should remain intact, something like this:
paramname | value |
--------------+--------------+
width, height | 240 x 400 |
param1 | some value 1 |
...
I'm thinking about concatenating based on the needed paramcategory, but if possible/needed, concatenation can happen for specific paramnames as well. Whatever is easier/simpler.
Any help please?
Looking at this problem from above, you are going to have to 'UNION' 2 queries together. The first part of the union is your concat'd results, the second your original rows. For the first part you are going to need to do a self join on this table, along the lines of
select concat(a.paramname, b.paramname), concat(a.value, b.value) from table a, table b where a.paramcategory = b.paramcategory
along those lines....
Actually if you swap the 2 parts of the union around, you'll keep the original column names too.

Hibernate Query in entire table with unique lines selects

I'm wondering how to filter Hibernate results.
For example, I have this example table:
--------------------------------------------
| ID | STRING | DATE |
--------------------------------------------
| 1 | "ABC" | 2014-11-07 21:45:00 |
--------------------------------------------
| 2 | "ABC" | 2014-11-07 22:45:00 |
--------------------------------------------
| 3 | "DCE" | 2014-11-07 22:48:00 |
--------------------------------------------
| 4 | "ABC" | 2014-11-07 23:48:00 |
--------------------------------------------
The result that I need is:
--------------------------------------------
| ID | STRING | DATE |
--------------------------------------------
| 3 | "DCE" | 2014-11-07 22:48:00 |
--------------------------------------------
| 4 | "ABC" | 2014-11-07 23:48:00 |
--------------------------------------------
All lines of table, BUT, when I have the same content in column STRING, the column with the most recent DATE is the one in result set.
In hibernate I know
- select ALL lines;
- select the repeated lines and keep only the most recent.
But I don't know how to combine the two situations together, and I can't find it referenced anywhere.
I have a fixed length in STRING, and I use a fake primary key in my code to identify the register, but the value is inserted by user, and I have no previous knowledge of the content in the column.
You can do this using a not exists clause:
select e.*
from example e
where not exists (select 1 from example e2 where e2.string = e.string and e2.date > e.date);
That is, select all rows where there is no other row with the same string and a larger date.