How can I replace nested for statement with mysql query? - mysql

Environment :
MySQL 5.7.x
Spring MVC
Table Data (name: TableA)
seq
level
name
order
parent_seq
1
1
name1
1
0
2
1
name2
2
0
3
2
sub1-1
1
1
4
2
sub1-2
2
1
5
2
sub2-1
1
2
6
3
third-2-1
1
5
7
3
third-1-1
1
3
Expected Result
seq
level
name
order
parent_seq
next_level
1
1
name1
1
0
2
3
2
sub1-1
1
1
3
7
3
third-1-1
1
3
2
4
2
sub1-2
2
1
1
2
1
name2
2
0
2
5
2
sub2-1
1
2
3
6
3
third-2-1
1
5
1 (last default value: 1)
Now I'm genenrating expected result with nested for statement(JAVA).
Is there any way to generate expected result only with MySQL Query?
The data stacked in random order in the table is sorted by ASC based on the level column, but check the parent_seq column so that it is sorted under the parent data. And if there are multiple data of the same level, sort by ASC based on the sort column value.
Thanks in advance!
++
EmbraceNothingButFuture's answer was great, but the query seems to work on MySQL 8. I'm using MySQL 5.7. Is there any way to use the query on MySQL 5.7?

Summary:
Use REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*") to extract the numbers and sort the datas using the numbers.
For MySQL v8 above, you can use LEAD() to generate the "next_level" column based on the "level" column
COALESCE() function for the last default value = 1
SELECT
t1.*,
COALESCE(LEAD(t1.level, 1) OVER(ORDER BY REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*")), 1) AS next_level
FROM TableA t1
ORDER BY REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*"), t1.level
See db<>fiddle

Related

Filtering duplicate rows based on multiple columns (QueryBuilder 4.2)

I've ran into a little difficulty when trying to filter top N results for a table.
Assume the following table:
ID, X, Y, Result0, Result1
-------------------------------
0 0 0 1 4
1 0 1 2 5
2 0 1 1 4
3 0 2 2 5
4 0 3 0 1
5 1 3 3 4
6 1 3 2 5
7 1 3 4 6
So, let's say I want to get the top 2 results for the highest Result0 value, using Result1 as a tie breaker if the Result0 values are equal, and having only distinct values for (X,Y),
if I'll run the following query:
$result = DB::table('table')
->orderBy('Result1', 'DSC')
->orderBy('Result0', 'DSC')
->take(300)
->get();
This code will return IDs 5,7, because they have the highest Result0 values, but the X,Y for these fields are identical, and I'd like to get only top result for distinct X,Y values.
I tried adding a
->groupBy('X','Y')
But it grouped the entries based on the database order of the entries (i.e the ID) rather than my sorting of that table.
Anyone has any idea how can I achieve my goal?

mysql search where 3 columns for row have the same value

id - in_id - nat_id
1 1 1
2 1 3
3 3 3
4 2 1
Is it possible to select with mysql only the values in the above table which are the same across the 3 columns, ie return 1 and 3?
Or is this kind of filter only possible post query with php?
Thanks,
John
This simple query should work for you:
SELECT id
FROM your_table
WHERE id = in_id
AND nat_id = in_id
;
Check example at SQLFiddle: SQLFiddle Example

Get the SQL column Value dynamically

I have a column in table A. the column name is Sequence number. The Structure of table A is numbers from 1,2,3,4.....3600.
Now on the basis of table A. I want the below output from the SQL select query for SQL server 2008.
seq no dynamic col
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
10 2
11 2
12 3
13 3
My Second column is getting generated at the run time.
And the business logic is that, if the seq number mod 6 = 0 then increment the value of dynamic column.
Thanks in advance
Try this:
select seqno, (seqno/6) +1 dynamiccol
from t
Fiddle Demo
Take this as pseudo code because I'm not familiar with SQL Server specifically, but it should give you somewhere to go.
SELECT
seq_no,
ROUNDDOWN(seq_no/6)+1 AS dynamic_col
FROM
my_table

What is the difference between MySQL LIMIT range of 0,500 and 1, 500?

If I want in MySQL rows 1 through 500, should I use LIMIT 0, 500 or LIMIT, 1, 500? What is the difference? Thanks!
The first one starts from the first record of the whole result, while the second one starts on the second record of the result.
Consider the following records
ID
1 -- index of the first record is zero.
2
3
4
5
6
if you execute
LIMIT 0, 3
-- the result will be ID: 1,2,3
LIMIT 1, 3
-- the result will be ID: 2,3,4
SQLFiddle Demo
OTHER(s)
Limit - MySQL Command (for more info)
In MySQL, the meaning of LIMIT n1, n2 is :
n1 : starting index
n2 : number of record/data you want to show
For example :
ID
-------------------------
1 ------------ > index 0
2
3
4
5
6
7
8
9
10 ------------ > index 9
Now if you write query like
SELECT * from tbl_name LIMIT 0,5
Output :
1
2
3
4
5
And if you write query like
SELECT * from tbl_name LIMIT 2,7
Output :
3
4
5
6
7
8
9
#JohnWoo That's not correct. The order of rows from a SELECT statement, with no ORDER BY clause, is unspecified. Therefore even though by visually looking at the output order of such a query it may seem to be in a specific order, that order is not guaranteed and therefore not reliable. If you require a result set to be ordered in a certain way you must use an ORDER BY clause.
ID
1
2
3
4
5 ------------ > index 0
6
7
8
9 ------------ > after 5 index add 4 value
10
If you want data from 5 to 9 so query should be
SELECT * from table_name LIMIT 5,4

SQL - counting rows with specific value

I have a table that looks somewhat like this:
id value
1 0
1 1
1 2
1 0
1 1
2 2
2 1
2 1
2 0
3 0
3 2
3 0
Now for each id, I want to count the number of occurences of 0 and 1 and the number of occurences for that ID (the value can be any integer), so the end result should look something like this:
id n0 n1 total
1 2 2 5
2 1 2 4
3 2 0 3
I managed to get the first and last row with this statement:
SELECT id, COUNT(*) FROM mytable GROUP BY id;
But I'm sort of lost from here. Any pointers on how to achieve this without a huge statement?
With MySQL, you can use SUM(condition):
SELECT id, SUM(value=0) AS n0, SUM(value=1) AS n1, COUNT(*) AS total
FROM mytable
GROUP BY id
See it on sqlfiddle.
As #Zane commented above, the typical method is to use CASE expressions to perform the pivot.
SQL Server now has a PIVOT operator that you might see. DECODE() and IIF() were older approaches on Oracle and Access that you might still find lying around.