Get the SQL column Value dynamically - sql-server-2008

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

Related

How can I replace nested for statement with mysql query?

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

Generate numbers based on a table column mysql

I have a table with the following rows:
ID Description Number
1 Test 1 4
2 Test 2 3
3 Test 3 5
4 Test 5 6
How do I create my query so that if I want ID 3, it generates the following based on the Number column:
Count
1
2
3
4
5
Thanks. :)
It looks like your rows are already uniquley identified. You need to query the row with id 3, and then preform an operation with php to count out to the end of the number set. 5 in this case. You could use arrays, and just loop throjgh the array for each number as well.

Duplicating rows in one select MySql query

At first I would like greet all Users and apologize for my english :).
I'm new user on this forum.
I have a question about MySQL queries.
I have table Items with let say 2 columns for example itemsID and ItemsQty.
itemsID ItemsQty
11 2
12 3
13 3
15 5
16 1
I need select itemsID but duplicated as many times as indicated in column ItemsQty.
itemsID ItemsQty
11 2
11 2
12 3
12 3
12 3
13 3
13 3
13 3
15 5
15 5
15 5
15 5
15 5
16 1
I tried that query:
SELECT items.itemsID, items.itemsQty
FROM base.items
LEFT OUTER JOIN
(
SELECT items.itemsQty AS Qty FROM base.items
) AS Numbers ON items.itemsQty <=Numbers.Qty
ORDER BY items.itemsID;
but it doesn't work correctly.
Thanks in advance for help.
SQL answer - Option 1
You need another table called numbers with the numbers 1 up to the maximum for ItemsQuantity
Table: NUMBERS
1
2
3
4
5
......
max number for ItemsQuantity
Then the following SELECT statement will work
SELECT ItemsID, ItemsQty
FROM originaltable
JOIN numbers
ON originaltable.ItemsQty >= numbers.number
ORDER BY ItemsID, number
See this fiddle -> you should always set-up a fiddle like this when you can - it makes everyone's life easier!!!
code answer - option 2
MySQL probably won't do what you want 'cleanly' without a second table (although some clever person might know how)
What is wrong with doing it with script?
Just run a SELECT itemsID, ItemsQty FROM table
Then when looping through the result just do (pseudo code as no language specified)
newArray = array(); // new array
While Rows Returned from database{ //loop all rows returned
loop number of times in column 'ItemsQty'{
newArray -> add 'ItemsID'
}
}//end of while loop
This will give you a new array
0 => 11
1 => 11
2 => 12
3 => 12
4 => 12
5 => 13
etc.
Select DISTINCT items.itemsID, items.itemsQty From base.items left outer join (select items.itemsQty as Qty from base.items) As Numbers On items.itemsQty <=Numbers.Qty
order by items.itemsID;
Use DISTINCT to remove duplicates. Read more here - http://dev.mysql.com/doc/refman/5.0/en/select.html
It seems like I understood what you asked differently than everyone else so I hope I answer you question. What I would basically do is -
create a new table for those changes.
Create a mysql procedure which given a line in the original table add new lines to the new table - http://dev.mysql.com/doc/refman/5.6/en/loop.html
Run this procedure for each line in the original table.
try this to get distinct values from both columns
SELECT DISTINCT itemsID FROM items
UNION
SELECT DISTINCT itemsQty FROM items

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.

MySQL: Matching inexact values using "ON"

I'm way out of my league here...
I have a mapping table (table1) to assign particular values (value) to a whole number (map_nu). My second table (table2), is a collection of averages (avg) for each user (user_id).
(I couldn't figure out how to properly make a markdown table, please feel free to edit!)
table1: table2:
(value)(Map_nu) (user_id)(avg)
---- -----
1 1 1 1.111
1.045 2 2 1.2
1.09 3 3 1.33333
1.135 4 4 1
1.18 5 5 1.389
1.225 6 6 1.42
1.27 7 7 1.07
1.315 8
1.36 9
1.405 10
The value Map_nu is a special number that each user gets assigned according to their average. I need to find a way to match the averages from table2 to the closest value in table1. I only need to match to the 2 digit past the decimal, so I've added the Truncated function
SELECT table2.user_id, map_nu
FROM `table1`
JOIN table2 ON TRUNCATE(table1.value,2)=TRUNCATE(table2.avg,2)
I still miss the values that don't match the averages exactly. Is there a way to pick the nearest truncated value or even to round to the second decimal? Rounding up/down wont matter as long as its applied to all values the same.
I am trying to have the following result (if rounded up):
(user_id)(Map_nu)
----
1 4
2 6
3 6
4 1
5 10
6 11
7 3
Thanks!
i think you might have to do this in 2 separate queries. there is no 'nearest' operator in sql, so you can either calculate it in your software, or you could use
select map_nu from table1 ORDER BY abs(value - $avg) LIMIT 1
inside a loop. however, that cannot be used as a join function as it requires the ORDER and LIMIT which are not valid as joins.
another way of looking at it is it seems that your map_nu and value are deterministic in relation to each other - value = 1 + ((map_nu - 1) * 0.045) - so maybe you could make use of that fact and calculate an integer based on that equation? assuming that relationship holds true for all values of map_nu.
This is an awkward database design. What is the data representing and what are you trying to solve? There might be a better way.
Maybe do something like...
SELECT a.user_id, b.map_nu, abs(a.avg - b.value)
FROM
table2 a
join table1 b
left join table1 c on abs(a.avg - b.value) > abs(a.avg - c.value)
where c.value is null
order by a.user_id
Doesn't actually produce the same output as the one you were expecting for (doesn't do any rounding). Though you should be able to tweak it from there. Above query will produce the output below (w/ data you've provided):
user_id map_nu abs(a.avg - b.value)
------- ------ --------------------
1 3 0.0209999999999999
2 5 0.02
3 8 0.01833
4 1 0
5 10 0.016
6 10 0.0149999999999999
7 3 0.02
Beware though if you're dealing with large tables. Evaluate the explain of the above query if it'll be practical to run it within MySQL or if better to be done outside it.
Note 2: Will produce duplicate rows if there are avg values that are equi-distant to value values within table1 (Ex. if value for map_nu's 11 and 12 are 2 and 3 and someone get's an avg of 2.5). Your question doesn't really specify what to do for that so you might want to take that into account.
Its taking a little extra work, but I figure the easiest way to get my results will be to map all values to the second decimal place in table1:
1 1
1.01 1
1.02 1
1.03 1
1.04 1
1.05 2
1.06 2
1.07 2
1.08 2
1.09 3
1.1 3
1.11 3
1.12 3
1.13 3
1.14 4
...
Thanks for the suggestions! Sorry I couldn't present the question more clear.