Renumbering the records in Oracle and SQL Server - sql

I have a table t with following values in col1 -
1
1
3
4
4
4
5
7
10
13
I need to renumber it as following, so it will erase the gaps between numbers.
1
1
2
3
3
3
4
5
6
7
I am able to find the gap ranges. Didn't find the way to renumber - tried to apply analytical function with row_num() but cannot get correct result. Code should work in both Oracle and SQL Server, so connect by level is probably not the best way.

That look like a DENSE_RANK, SQL-Server:
WITH CTE AS
(
SELECT Col1, RANK = DENSE_RANK() OVER (ORDER BY Col1 ASC)
FROM dbo.Table1
)
UPDATE CTE SET Col1 = RANK
WHERE Col1 <> RANK
I'm not familiar with Oracle (anymore) but there's also a Dense_Rank function.
Demo
COL1
1
1
2
3
3
3
4
5
6
7

Related

Calculating median of 3 columns in a BigQuery table

I am trying to build a query to calculate median of 3 column values. My table looks like below,
Item
Column 1
Column 2
Column 3
A
10
12
4
B
5
14
20
C
15
5
4
I want to be able to output,
Item
Column 1
Column 2
Column 3
Median
A
10
12
4
10
B
5
14
20
14
C
15
5
4
5
I have tried percentile_cont() but that seems to be only for values in a single column. How do i achieve this?
Consider below approach
select *,
( select distinct percentile_disc(col, 0.5) over()
from unnest([Column1, Column2, Column3]) as col
) AS Median
from your_table
if applied to sample data in your question - output is
Have you tried this:
select Col1, Col2, Col3,
PERCENTILE_CONT([Col1, Col2, Col3], 0.5) OVER() AS Median
from tableName

Row Number with specific window size

I want to group records by row numbers.
Like from row 1-3 in group 1 , 4-6 in group 2 , 7-9 in group 3 and so on.
Suppose below is the table structure:
Row NumberDataValue
1 A 10
2 A 5
3 A 1
4 A 33
5 A 2
6 A 127
1 B 1
2 B 0
3 B 7
4 B 7
5 B 5
6 B 8
7 B 1
8 B 0
I want a output like this:
GroupValue
1 10
1 5
1 1
2 33
2 2
2 127
1 1
1 0
1 7
2 7
2 5
2 8
3 1
3 0
I am using Oracle 11G.
I can achieve this using PL/SQL. But I have to use SQL only. As I have to use this query in a reporting tool.
If this is a duplicate question please provide the link of the answered question.
Subtract 1 from the column "RowNumber" and divide by 3.
Then use TRUNC() to get the integer part:
SELECT TRUNC(("RowNumber" - 1) / 3) + 1 "Group",
"Value"
FROM tablename
See the demo.
I would assume the name of the first column is ordering.
You can do:
select
1 + trunc(row_number() over(partition by data order by ordering) - 1) / 3,
value
from t
What you show looks like the output from something like this:
select ceil(rn/3) as grp, value
from your_table
order by rn;
Note that "row number" and "group" are reserved words/phrases which should not be used as column names. I used rn and grp instead.
I think the ceiling function is the simplest way to arrive at what you want. If you want to base it on the RowNumber column:
select ceil( RowNumber / 3.0) as grouping
If you want to calculate it yourself using row_number():
select ceil( row_number() over (order by RowNumber) / 3.0 ) as grouping

How to get average runs for each over in SQL?

The first six balls mean first over, next six balls mean second over & so on than how to get average runs for each over.
input as
Ball no Runs
1 4
2 6
3 3
4 2
5 6
6 1
1 2
2 4
3 6
4 3
5 1
6 1
1 2
output should be:
Over no avg runs
1 3.66
2 2.83
As Gordon Linoff suggested, SQL table represents unordered sets, So you have to use an ordered column in your table. If you can use such a column you may use below query -
SELECT Over_no AVG(Runs) avg_runs
FROM (SELECT Ball_no, Runs, CEIL(ROW_NUMBER() OVER(ORDER BY ORDER_COLUMN, Ball_no) RN / 6) Over_no
FROM YOUR_TABLE)
GROUP BY Over_no;
I have managed to solve my problem with the following query:
SELECT ROWNUM OVER_NO, AVG_RUNS
FROM(
SELECT ROWNUM RN,
ROUND(AVG(RUNS)OVER(ORDER BY ROWNUM RANGE BETWEEN CURRENT ROW AND 5 FOLLOWING),2) AVG_RUNS
FROM TABLE_NAME
)
WHERE RN=1 OR RN=7;

SQL query to take top elements of ordered list on Apache Hive

I have the table below in an SQL database.
user rating
1 10
1 7
1 6
1 2
2 8
2 3
2 2
2 2
I would like to keep only the best two ratings by user to get:
user rating
1 10
1 7
2 8
2 3
What would be the SQL query to do that? I am not sure how to do it.
It will work
;with cte as
(select user,rating, row_number() over (partition by user order by rating desc) maxval
from yourtable)
select user,rating
from cte
where maxval in (1,2)

How to ignore certain similar rows when select

I have the following table
Id col1 col2 col3
1 c 2 m
2 c 3 6
2 b d u
3 e 6 9
4 1 v 8
4 2 b t
4 4 5 g
As you can see, there are duplicate value in id column, 2 and 4. I only want to select rows with unique id value and ignore the following rows with duplicate id value. I just want to keep the first of the rows with duplicate values
1 c 2 m
2 c 3 6
3 e 6 9
4 1 v 8
There is FK constraint, so I cannot delete rows with duplicate values.
I am using SQL SERVER 2008 R2
Any reply will be appreciated.
You can use row_number to number each row with the same id. Then you can select only the first row per id:
select *
from (
select row_number() over (partition by id order by col1, col2, col3) rn
from YourTable
) as SubQueryAlias
where rn = 1
The subquery is required because SQL Server doesn't allow row_number directly in the where clause.