How to Query by line in SQL [duplicate] - sql

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 3 months ago.
I have the query and table below, how do I select the 1st line of each category of column TeamboardId?
SELECT * FROM Job WHERE HandLingTimeSeconds = '60'
JobId
TeamboardId
1
1
2
1
3
1
4
2
5
2
6
2
The expected result should be
JobId
TeamboardId
1
1
4
2

You can probably use a window function such as ROW_NUMBER() like in the below query :
WITH j AS
(
SELECT Job.*, ROW_NUMBER() OVER (PARTITION BY TeamboardId ORDER BY JobId) AS rn
FROM Job
WHERE HandLingTimeSeconds = '60'
)
SELECT *
FROM j
WHERE rn = 1

Related

How to append a count number in duplicate values in a column and update in SQL Server?

Currently my table looks like this; I want to add the count numbers with distinct InstanceId and duplicate values.
Id
InstanceId
Name
1
1
DiscoveryInstance
2
1
DiscoveryInstance
3
2
ETLInstance
4
3
DiscoveryInstance
5
3
DiscoveryInstance
6
2
ETLInstance
7
2
ETLInstance
I want the output to be like this:
Id
InstanceId
Name
1
1
DiscoveryInstance
2
1
DiscoveryInstance_Backup_1
3
2
ETLInstance
4
3
DiscoveryInstance
5
3
DiscoveryInstance_Backup_1
6
2
ETLInstance_Backup_1
7
2
ETLInstance_Backup_2
I don't want to update the first value and update should start with the next duplicate value in the column.
How to update this table to make this output possible in SQL Server query?
EDIT This solution addresses the ORIGINAL question and original output. This is no longer valid because you changed your desired output.
You could use rank() and concat in this manner:
with cte as (select id, name, rank() over (partition by name order by id) as name_rank
from my_table
)
select t.id,
case
when c.name_rank = 1 then t.name
else concat(t.name, '_Backup_', c.name_rank - 1)
end name
from my_table t
join cte c
on t.id = c.id
Output:
id
name
1
DiscoveryInstance
2
DiscoveryInstance_Backup_1
3
ETLInstance
4
DiscoveryInstance_Backup_2
5
DiscoveryInstance_Backup_3
6
ETLInstance_Backup_1
DB-fiddle found here. I see you updated the question after I posted this answer by adding another column, but that does not look important at the moment.
EDIT
This is an updated answer (thanks Guido) that would address your newly updated output:
with cte as (select id, name, rank() over (partition by name, instanceid order by id) as name_rank
from mytable
)
select t.id,
case
when c.name_rank = 1 then t.name
else concat(t.name, '_Backup_', c.name_rank - 1)
end name
from mytable t
join cte c
on t.id = c.id
Another option is using the row_number() like this
This solution uses your new column instanceid to get the correct data
select t.id,
case when rownumber > 1 then t.Name + '_Backup_' + convert(varchar(10), t.rownumber - 1)
else t.Name
end
from ( select t.id,
t.name,
row_number() over (partition by t.Name, t.instanceid order by t.id) as rownumber
from mytable t
) t
order by t.id
See this DBFiddle
output is
id
(No column name)
1
DiscoveryInstance
2
DiscoveryInstance_Backup_1
3
ETLInstance
4
DiscoveryInstance
5
DiscoveryInstance_Backup_1
6
ETLInstance_Backup_1
7
ETLInstance_Backup_2

pick all positive least numbers from data set [duplicate]

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Oracle group using min date
(3 answers)
GROUP BY with MAX(DATE) [duplicate]
(6 answers)
Closed 3 years ago.
I have below data in a table
ID AMOUNT DAYS
1 10 1
1 20 2
1 30 3
1 1 4
2 34 1
2 234 2
2 234 3
2 34 4
3 3 1
3 3 2
3 23 3
3 20 4
I want below results as all amounts which have least days of a ID
ID AMOUNT DAYS
1 10 1
2 34 1
3 3 1
Please suggest a sql query to pick this desired output
For your example, you can simply do:
select t.*
from t
where t.days = 1;
If 1 is not fixed, then a correlated subquery is one method:
select t.*
from t
where t.days = (select min(t2.days) from t t2 where t2.id = t.id);
Another method is aggregation:
select t.id, min(t.days) as min_days,
min(t.amount) keep (dense_rank first order by t.days asc) as min_amount
from t
group by t.id;
Of course row_number()/rank() is another alternative.
With an index on (id, days) and a large table, one of the above methods may be faster in practice.
You can use rank() function
select ID, Amount, Days from
(
select rank() over (partition by ID order by days) as rn,
t.*
from tab t
)
where rn = 1;
Demo
First group by id to find the min days for each id and then join to the table
select t.*
from tablename t inner join (
select id, min(days) days
from tablename
group by id
) g on g.id = t.id and g.days = t.days

Oracle query to find the top 2 item per group [duplicate]

This question already has answers here:
Get top results for each group (in Oracle)
(5 answers)
ORACLE - find a concrete result inside a LOOP (OR SIMILAR) [duplicate]
(1 answer)
Closed 2 years ago.
I want to right a sql query to find the top 2 item per group in oracle.
The table contains:
P_id Price GroupX
1 10 a
2 5 a
3 5 a
4 4 b
5 8 b
6 6 b
Output should be:
P_id Price GroupX
1 10 a
2 5 a
5 8 b
6 6 b
What I have tried is:
Select * from table
group by GroupX
order by price desc
limit 2
How about
Select rnk,P_id, Price, GroupX
from (
select P_id, Price, GroupX,
RANK () OVER (PARTITION BY GroupX
ORDER BY Price DESC
) AS rnk
from table
)
where rnk <= 2;
You can use the ROW_NUMBER() analytic function:
SELECT p_id,
price,
GroupX
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY groupX
ORDER BY Price DESC ) AS rn
FROM table_name t
)
WHERE rn <= 2;

Fetch a fixed number of rows in SQL query in Oracle [duplicate]

This question already has answers here:
Paging with Oracle
(7 answers)
Closed 8 years ago.
Please help me to write an SQL query in the Oracle database. There is table called tbl and it has 12 rows. I want to select first 4 rows first then next 4 and the last 4 rows.
Can any anyone tell me how can I do this in Informix.
EDIT: now should be fixed with 3-level select:
select * from (
select q1.*, rownum as rn from ( --get correct rownum
select * from tbl order by column --get correct order
) q1
) q2
where q2.rn between 1 and 4; -- filter
for first part.
For second and third part:
where q2.rn between 5 and 8
where q2.rn between 9 and 12
There is nothing called as first rows, last rows, "n" rows unless you explicitly specify an ORDER BY and then select the required rows.
Top-n Row Limiting feature in Oracle 12c on ward:
SQL> select * from order_test order by val;
VAL
----------
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
20 rows selected.
First 4 rows :
SQL> SELECT val
2 FROM order_test
3 ORDER BY VAL
4 FETCH FIRST 4 ROWS ONLY;
VAL
----------
1
1
2
2
Next 4 rows(look at OFFSET) :
SQL> SELECT val
2 FROM order_test
3 ORDER BY VAL
4 OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;
VAL
----------
3
3
4
4
Finally, next 4 rows with OFFSET 8 rows :
SQL> SELECT val
2 FROM order_test
3 ORDER BY VAL
4 OFFSET 8 ROWS FETCH NEXT 4 ROWS ONLY;
VAL
----------
5
5
6
6
You can use rownum:
select * from (select t.*, rownum rn from tbl t) where rn between 1 and 4;
/
select * from (select t.*, rownum rn from tbl t) where rn between 5 and 8;
/
select * from (select t.*, rownum rn from tbl t) where rn between 9 and 12;
/
If you're using order by clause then use row_number() (documentation)
select * from (select t.*, row_number() over (order by column_name) rn from tbl t) where rn between 1 and 4;
/
select * from (select t.*, row_number() over (order by column_name) rn from tbl t) where rn between 5 and 8;
/
select * from (select t.*, row_number() over (order by column_name) rn from tbl t) where rn between 9 and 12;
/

SQL show only the top 2 comments for each actionid [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Selecting the top n rows within a group by clause
I have the following data:
id actionid commentid
1 1 1
2 1 2
3 1 3
4 2 1
I want to create a sql to only show the top 2 comments for each actionid. In that case I the sql should only return id (1,2,4)
Thanks
SELECT id,
actionid,
commentid
FROM (
SELECT id,
actionid,
commentid,
row_number() over (partition by actionid order by id) rn
FROM your_table
) t
WHERE rn <= 2