SQL oracle Select condition in group - sql

Let's suppose I have a table with 3 columns:
ID | GroupId | DateCreatedOn |
I want to select the datas grouped by GroupId so:
select GroupId from tableName group by GroupId;
But what if I want to execute another select on each group? let's suppose now that I want the last created row (DateCreatedOn) of each group?
Also, I would like to retrieve ALL the columns and not only the GroupId.
Im kind of lost because I only have GroupId available.
Please provide some explanation and not only the correct query.

You can use ROW_NUMBER for this:
SELECT ID, GroupId, DateCreatedOn
FROM (
SELECT ID, GroupId, DateCreatedOn,
ROW_NUMBER() OVER (PARTITION BY GroupId
ORDER BY DateCreatedOn DESC) AS rn
FROM mytable) t
WHERE t.rn = 1
rn field is equal to 1 for the record having the most recent DateCreatedOn value within each GroupId partition.

You can get the values with the maximum of another column using KEEP ( DENSE_RANK [FIRST|LAST] ORDER BY ... ) in the aggregation:
SELECT GroupID,
MAX( ID ) KEEP ( DENSE_RANK LAST ORDER BY DateCreatedOn ) AS id
MAX( DateCreatedOn ) AS DateCreatedOn
FROM table_name
GROUP BY GroupId
You can also do it using ROW_NUMBER():
SELECT ID,
GroupID,
DateCreatedOn
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY GroupID
ORDER BY DateCreatedOn DESC, ID DESC ) AS RN
FROM table_name t
)
WHERE RN = 1
(ID DESC is added to the ORDER BY to get the maximum ID for the latest DateCreatedOn to give the same result as the first query; if you don't have a deterministic order then you are likely to get whichever row the database produces first and the result can be non-deterministic)

Related

checking if the values in one column are in order for the ID field using SQL

I want to choose one record per ID, based on the values in the sort field.
if there is a gap of more than 1 in the Sort filed I would want to assign the maximum sort value for that ID field. If the sort field is in order (eg for ID B the sort filed is 9,10, 11,12)
I would like to choose the minimum value for the ID.
enter image description here
Try this:
SELECT i.ID, MIN(i.sort) as sort
FROM input as i
INNER JOIN
(
Select ID, MAX(diff) as gap
FROM
(
SELECT ID, Sort, Rank,
LEAD(sort) OVER (PARTITION BY ID ORDER BY sort desc) as lead,
ABS(sort - LEAD(sort) OVER (PARTITION BY ID ORDER BY sort desc)) as diff
FROM input
) as a
WHERE diff IS NOT NULL
GROUP BY ID) as s
ON i.ID=s.ID
WHERE s.gap=1
GROUP BY i.ID
UNION
SELECT i.ID, MAX(i.sort) as sort
FROM input as i
INNER JOIN
(
Select ID, MAX(diff) as gap
FROM
(
SELECT ID, Sort, Rank,
LEAD(sort) OVER (PARTITION BY ID ORDER BY sort desc) as lead,
ABS(sort - LEAD(sort) OVER (PARTITION BY ID ORDER BY sort desc)) as diff
FROM input
) as a
WHERE diff IS NOT NULL
GROUP BY ID) as s
ON i.ID=s.ID
WHERE s.gap<>1
GROUP BY i.ID
I have used multiple sub-query. You can use CTE or create intermediate tables if required.
db<>fiddle link here

Select the most recent row where 2 columns contain the same value

I have a table of street codes and county codes. I need to only select the most recent row (ordered by created date) of any rows where these 2 columns are the same.
Ex.
Here only the last row should be selected, since it has the newest created date, where the Kommunekode and Vejkode are the same.
How can I filter my select statement to allow this logic? I tried using the distinct keyword, but that does not take the Created date into account.
My current code for the view:
SELECT
Infohub_RowId,
Infohub_CreatedDate,
Id,
Sekvensnummer,
Tidspunkt,
Operation,
Kommunekode,
Vejkode,
Oprettet,
Aendret,
Navn,
Vejnavn,
Navngivenvej_id,
Aendret AS Infohub_ValidityDate
FROM (
SELECT
Infohub_RowId,
Infohub_CreatedDate,
Sekvensnummer,
Tidspunkt,
Operation,
Id,
Kommunekode,
Vejkode,
Oprettet,
Aendret,
Navn,
Vejnavn,
Navngivenvej_id,
ROW_NUMBER() OVER(PARTITION BY Id ORDER BY Aendret DESC) AS RowNum
FROM
Dawa.tDelta_Vejstykke) AS x
WHERE x.RowNum = 1
The view should "clean up" the data, by selecting the newest duplicate records.
use Infohub_CreatedDate in order by and Kommunekode,Vejkode these two column in partition by
SELECT
Infohub_RowId,
Infohub_CreatedDate,
Id,
Sekvensnummer,
Tidspunkt,
Operation,
Kommunekode,
Vejkode,
Oprettet,
Aendret,
Navn,
Vejnavn,
Navngivenvej_id,
Aendret AS Infohub_ValidityDate
FROM (
SELECT
Infohub_RowId,
Infohub_CreatedDate,
Sekvensnummer,
Tidspunkt,
Operation,
Id,
Kommunekode,
Vejkode,
Oprettet,
Aendret,
Navn,
Vejnavn,
Navngivenvej_id,
ROW_NUMBER() OVER(PARTITION BY Kommunekode,
Vejkode ORDER BY Infohub_CreatedDate DESC) AS RowNum
FROM
Dawa.tDelta_Vejstykke) AS x
WHERE x.RowNum = 1
You want row_number() but Kommunekode, Vejkode should be in partition clause :
SELECT t.*
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY Kommunekode, Vejkode ORDER BY Infohub_CreatedDate DESC) AS Seq
FROM Dawa.tDelta_Vejstykke t
) t
WHERE Seq = 1;

How to select distinct records based on condition

I have table of duplicate records like
Now I want only one record from duplicate records which has latest created date as How can I do it ?
use row_number():
select EnquiryId, Name, . . .
from (select t.*,
row_number() over (partition by enquiryID order by CreatedDate desc) as seqnum
from table t
) t
where seqnum = 1;
Use ROW_NUMBER function to tag the duplicate records ordered by CreatedDate, like this:
;with CTE AS (
select *, row_NUMBER() over(
partition by EnquiryID -- add columns on which you want to identify duplicates
ORDER BY CreatedDate DESC) as rn
FROM TABLE
)
select * from CTE
where rn = 1

How to reverse the table that comes from SQL query which already includes ORDER BY

Here is my query:
SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
This the result:
How can I reverse this table based on date (Column2) by using SQL?
You can use the first query to get the matching ids, and use them as part of an IN clause:
SELECT id, rssi1, date
FROM history
WHERE id IN
(
SELECT TOP 8 id
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
)
ORDER BY date ASC
You could simply use a sub-query. If you apply a TOP clause the nested ORDER BY is allowed:
SELECT X.* FROM(
SELECT TOP 8 id, Column1, Column2
FROM dbo.History
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) X
ORDER BY Column2
Demo
The SELECT query of a subquery is always enclosed in parentheses. It
cannot include a COMPUTE or FOR BROWSE clause, and may only include an
ORDER BY clause when a TOP clause is also specified.
Subquery Fundamentals
try the below :
select * from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC ) aa order by aa.date DESC
didn't run it, but i think it should go well
WITH cte AS
(
SELECT id, rssi1, date, RANK() OVER (ORDER BY ID DESC) AS Rank
FROM history
WHERE (siteName = 'CCL03412')
)
SELECT id, rssi1, date
FROM cte
WHERE Rank <= 8
ORDER BY Date DESC
I have not run this but i think it will work. Execute and let me know if you face error
select id, rssi1, date from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) order by date ;

Find n largest values in a column

I am trying to find the n largest numbers in a particular column in SQL Server.
We can find the largest value in a column and the 2nd largest value easily.
But how do I find say, 5 largest values in a column ?
You tagged this both for MySQL and SQL Server. In SQL Server you can use TOP:
SELECT TOP 5 yourColumn
FROM yourTable
ORDER BY someColumn DESC;
TOP limits the number of rows returned. To get the data with the largest/smallest values you will want to include an ORDER BY.
In MySQL you will use LIMIT
Another way to do this in SQL Server is using row_number():
select id
from
(
select id, row_number() over(order by id desc) rn
from yourtable
) x
where rn <= 5
See SQL Fiddle With Demo
In MySql you can use [LIMIT {[offset,] row_count }] to do this like so:
...
ORDER BY SomeField DESC
LIMIT #n;
For SQL Server you can use the TOP(n) to get the top n:
SELECT TOP(#n) SomeFieldName
FROM TABLE
ORDER BY SomeField DESC
For example:
SELECT TOP 5 items_sold
FROM tbl_PRODUCT
ORDER BY items_sold dESC
Update: If you have another table families with a foreign key family_ID to products table, and you want to find all products with the top n family id's. Then you can dot this:
SELECT *
FROM Products WHERE family_ID IN
(
SELECT TOP 5 family_ID
FROM families
ORDER BY family_ID DESC
)
Update 2: The topmost product in each family:
;WITH cte
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY family_ID ORDER BY items_sold DESC) row_num
FROM #Products
)
SELECT * FROM cte
where row_num = 1
Order by family_ID
Here is alive demo
sql server
select min(val)
from your_table
where val in (select top 5 val from your_table order by val desc)
mysql
select min(val)
from your_table
where val in (select val from your_table order by val desc limit 5)