I have a strange request in mySQL. I found many ways to do this for pairs of combinations or a certain other number by adding more joins, but I am wondering if there is a dynamic way of doing it for any number of combinations.
To explain if I have a table table has 1 column (column_id) and (column_text)
Id | Text
--------
1 | A
2 | B
3 | B
4 | B
5 | A
Then by running a procedure GetCombinations with parameter A should yield:
CombinationId | Combinations
---------------------------
1 | 1
2 | 5
3 | 1,5
by running a procedure GetCombinations with parameter B should yield:
CombinationId | Combinations
---------------------------
1 | 2
2 | 3
3 | 4
4 | 2,3
5 | 2,4
6 | 3,4
7 | 2,3,4
Obviously the larger the number, then I expect an exponential increase of results.
Is such a query even possible? All I could find was results using Joins limiting the length of each result to the number of Joins.
Thank you
UPDATE
I have found an article here but the maximum number of combinations should be small (max 20 or so). In my case with a 100 combinations I calculated that it would produce: 9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000099 rows (lol)
So I will classify my answer as infeasible
However is there a way to get this result with max 2 combinations?
CombinationId | Combinations
---------------------------
1 | 2
2 | 3
3 | 4
4 | 2,3
5 | 2,4
6 | 3,4
I have found a query to get all combinations using JOIN but I am not sure how to produce the combination id and also how to get the individual rows.
UPDATE 2
Solved it using
SELECT #rownum := #rownum + 1 AS 'CombinationId'
cross join (select #rownum := 0) r
And I did the query with UNION ALL
What you are trying to do is to generate the Power Set of the set of all elements with field Text == <parameter>. As you already found out, this number grows exponentially with the length of the input array.
If you can solve it in other language (say, php), take a look at this:
Finding the subsets of an array in PHP
Related
I have a table:
id | created
1 | 1563220108
2 | 1563220408
3 | 1563220608
4 | 1563220808
5 | 1563220908
I want to find the lowest ID, where the difference between the current row and the other row is more than 5 minutes.
If you look at my sample data, the difs are as follows:
id | created | dif
1 | 1563220108 | null
2 | 1563220408 | 300
3 | 1563220608 | 500
4 | 1563220808 | 700
5 | 1563220908 | 800
5 x 60 = 300. So, in this case, I would like 2 to be returned.
If id = 2, was instead 301 seconds apart, then it would need to return id = 3.
I am struggling to get my brain to figure out how to write a query that looks at row 1, then row X + 1, then row X + 2 etc. It's not directly comparing the NEXT row. It must compare the first row with the next row, then the first row with the 3rd row, then first row with the 4th row and so forth. Is this even possible with mysql?
UPDATE
Version: 10.1.36-MariaDB
UPDATE 2
I have a database that stores points every couple of seconds. I am trying to write a script that deletes any points that are less than 5 minutes apart. The goal is to decrease the total size of the database, because I don't need to store so many points. I only need points once every 15 minutes or so.
So to do this, I need a script that can find the first id in the table, where the difference between this id and another following row, is bigger than 5 minutes. SO I take it back. It needs to not compare X + 2 and X + 3. It must ALWAYS just compare it with the next value!
So I need a table like this:
id | created | dif
1 | 1563220108 | null
2 | 1563220408 | 300
3 | 1563220608 | 200
4 | 1563220808 | 200
5 | 1563220908 | 100
From this, I should be able to do what I need to do. Going to fiddle and see if I can get this myself.
If the table is named time_data
SELECT AA.id, MIN(BB.id)
FROM time_data AA
INNER JOIN time_data BB
ON TIMESTAMPDIFF(MINUTE, AA.created, BB.created) > 5
GROUP BY AA.id
You can use a correlated subquery and ordering:
select t.*
from t
where not exists (select 1
from t t2
where t2.created < t.created and
t2.created >= t.created - 5 * 60
)
order by t.id asc
limit 1;
ID|Round
1 | 1
2 | 2
3 | 2
4 | 1
1 | 3
4 | 4
New to SQL so please forgive me if I bungle the lexicon. I'm trying to figure out how to specify a where clause so I can isolate all rows with IDs that match IDs occurring in Round 1 (regardless of round). The preferred output would be this:
ID|Round
1 | 1
4 | 1
1 | 3
4 | 4
ID 1 and 4 occurred in Round 1, so I want all rows that have ID 1 or 4 (and to exclude IDs that didn't occur in Round 1 ,i.e. IDs 2 and 3).
Any help would be appreciated as I can't seem to formulate a search that turns up an answer to this problem. Working in MySQL if that makes a difference.
This should work:
select * from table where id in(select id from table where round = 1
I have a mysql table like this with about 100 rows
id | text | weight
---------------------
1 | textA | 2
2 | textB | 3
3 | textC | 8
...
and I am trying to create a query that would return a random set of rows (but at least 3) of this table, whose sum of weight would be equal to 10. So as a result I would get a number of rows X that sum up to 10.
Could you suggest a way to achieve this? Would it be some sort of plsql script or what?
Thanks!
I have an MySQL table creatures:
id | name | base_hp | quantity
--------------------------------
1 | goblin | 5 | 2
2 | elf | 10 | 1
And I want to create creature_instances based on it:
id | name | actual_hp
------------------------
1 | goblin | 5
2 | goblin | 5
3 | elf | 10
The ids of creatures_instances are not important and not relevant to creatures.ids.
How can I make it with just the MySQL in the most optimal (in terms of execution time) way? The single query would be best, but procedure is ok too. I use InnoDB.
I know that with a help of e.g. php I could:
select each row separately,
make for($i=0; $i<line->quantity; $i++) loop in which I insert one row to creatures_instances for each iteration.
The most efficient way is to do everything in SQL. It helps if you have a numbers table. Without one, you can generate the numbers in a subquery. The following works up to 4 copies:
insert into creatures_instances(id, name, actual_hp)
select id, name, base_hp
from creatures c join
(select 1 as n union all select 2 union all select 3 union all select 4
) n
on n.n <= c.quantity;
I can't figure out how to implement MySQL query more efficiently in this situation:
Table1
id | reg_id | lang_id |
---|--------|---------|
1 | 9 | 3 |
---+--------+---------|
2 | 7 | 8 |
---+--------+---------|
3 | 9 | 3 |
---+--------+---------|
4 | 1 | 1 |
---+--------+---------|
5 | 3 | 8 |
---+--------+---------|
6 | 7 | 22 |
---+--------+---------|
...more
I need to fetch 12 rows in total from the table above on three different WHERE conditions, 4 rows for each condition, for example:
SELECT id FROM table1 WHERE reg_id = 9 AND lang_id = 3 LIMIT 4
SELECT id FROM table1 WHERE reg_id = 3 AND lang_id = 8 LIMIT 4
SELECT id FROM table1 WHERE reg_id = 1 AND lang_id = 1 LIMIT 4
This is where I get confused:
All 12 rows need to be filled with data from three queries above, 4 records each.
But if the 1st query returns only 2 records, then its missing rows need to be filled with records from the 2nd query, so, in this case, the 2nd query will need to return 6 rows. But if the 2nd query has only 3 records, then its space needs to be filled with records from the 3rd query, so in this case, the 3rd query will need to return 7 rows.
So in total there have to be 12 rows filled.
I can do it with PHP statements by going back and forth to the database, counting rows and querying for the next set of data, but it does not look efficient to me, so I'm trying to figure out if the logic can be done inside a query via sub-queries or something. So single query could return the required data.
Can someone advice an idea?