get the field with longest string for same id value - sql

I have to get the row with longest string value for same id fields.
create table test(
id number,
test_data varchar2(20)
);
insert all
into test values (1,'aaa')
into test values (1,'a')
into test values (1,'abxw')
into test values (2,'aaa')
into test values (2,'tris')
select * from dual;
my desired output is
1 abxw --longest string
2 tris
how can I get the required output?? I am not getting any idea.
guys what about using cursor. can we use cursor for this purpose?? Does anyone have any idea? Is it possible??
Thank You.

I like using partition for these kind of queries:
select id,test_data from (
select
id, test_data,
row_number() over( partition by id order by length(test_data) desc) as rnum
from
test
) where rnum=1
http://www.sqlfiddle.com/#!4/66d4c/20
Of course, the nice thing about this is that if you decide that you want another tiebreak (e.g., alphabetically), you just need to add that to your order by clause. Which, by the way is not a bad idea, that way your result set will not be non-deterministic.

You can try this query. It will return multiple results if multiple strings have the longest length per id:
select
t1.id, t1.test_data
from
test t1
join
(select id, max(length(test_data)) as len from test group by id) t2
on t1.id = t2.id and length(t1.test_data) = t2.len
Demo: http://www.sqlfiddle.com/#!4/66d4c/6

I think the analytic (window) function RANK() is the best way to accomplish this.
SELECT id, test_data FROM (
SELECT id, test_data
, RANK() OVER ( PARTITION BY id ORDER BY LENGTH(test_data) DESC ) AS the_rank
FROM test
) WHERE the_rank = 1
If you want only one record, then you can do the following:
SELECT id, test_data FROM (
SELECT id, test_data
, RANK() OVER ( PARTITION BY id ORDER BY LENGTH(test_data) DESC ) AS the_rank
FROM test
ORDER BY the_rank
) WHERE rownum = 1

Related

Get latest record from a table based on 2 columns in hive

I want to get the latest record from my source table based on num and id columns and insert in my target table.
Scenario is explained in the attached screen shot. For latest record date column can be used.
Screenshot
Thanks.
Select num,id, date
FROM
(
Select *, ROW_NUMBER() OVER(partition by num,id Order by date desc) as rnk
FROM source_table
)a
WHERE rnk = 1;
by using corelated Subquery
select * from your_table t
where t.date= (
select max(date) from your_table t1
where t1.num=t.num and t1.id=t.id
)
You can do it using max() function
select num,id,max(date) from your_table t
group by num,id
SELECT NUM,ID,DATE FROM TABLE_TEMP
QUALIFY RANK OVER(PARTITION BY NUM,ID ORDER BY DATE DESC)=1;
You can do this using single line query
SELECT NUM,ID,DATE FROM TABLE_TEMP
QUALIFY RANK OVER(PARTITION BY NUM,ID ORDER BY DATE DESC)=1;

SQL query to get maximum value for each day

So I have a table that looks something like this:
Now, I want the max totalcst for both days, something like this:
I tried using different variations of max and the Row_number funtion but still can't seem to get the result I want. My query:
select date,pid,max(quan*cst), totalcst
from dbo.test1
group by date, pid
But this returns all the records. So if somebody can point me towards the right direction, that would be very helpful.
Thanks in advance!
ROW_NUMBER should work just fine:
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY [date] ORDER BY totalcst)
FROM dbo.YourTable
)
SELECT [date],
pid,
totalcst
FROM CTE
WHERE RN = 1
;
Here is one simple way:
select t.*
from test1 t
where t.totalcst = (select max(t2.totalcst) from test1 t2 where t2.date = t.date);
This often has the best performance if you have an index on (date, totalcst). Of course, row_number()/rank() is also a very acceptable solution:
select t.*
from (select t.*, row_number() over (partition by date order by totalcst desc) as seqnum
from test1
) t
where seqnum = 1;

how to get the distinct records based on maximum date?

I'm working with Sql server 2008.i have a table contains following columns,
Id,
Name,
Date
this table contains more than one record for same id.i want to get distinct id having maximum date.how can i write sql query for this?
Use the ROW_NUMBER() function and PARTITION BY clause. Something like this:
SELECT Id, Name, Date FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date desc) AS ROWNUM
FROM [MyTable]
) x WHERE ROWNUM = 1
If you need only ID column and other columns are NOT required, then you don't need to go with ROW_NUMBER or MAX or anything else. You just do a Group By over ID column, because whatever the maximum date is you will get same ID.
SELECT ID FROM table GROUP BY ID
--OR
SELECT DISTINCT ID FROM table
If you need ID and Date columns with maximum date, then simply do a Group By on ID column and select the Max Date.
SELECT ID, Max(Date) AS Date
FROM table
GROUP BY ID
If you need all the columns but 1 line having Max. date then you can go with ROW_NUMBER or MAX as mentioned in other answers.
SELECT *
FROM table AS M
WHERE Exists(
SELECT 1
FROM table
WHERE ID = M.ID
HAVING M.Date = Max(Date)
)
One way, using ROW_NUMBER:
With CTE As
(
SELECT Id, Name, Date, Rn = Row_Number() Over (Partition By Id
Order By Date DESC)
FROM dbo.TableName
)
SELECT Id --, Name, Date
FROM CTE
WHERE Rn = 1
If multiple max-dates are possible and you want all you could use DENSE_RANK instead.
Here's an overview of sql-server's ranking function: http://technet.microsoft.com/en-us/library/ms189798.aspx
By the way, CTE is a common-table-expression which is similar to a named sub-query. I'm using it to be able to filter by the row_number. This approach allows to select all columns if you want.
select Max(Date) as "Max Date"
from table
group by Id
order by Id
Try with Max(Date) and GROUP BY the other two columns (the ones with repeating data)..
SELECT ID, Max(Date) as date, Name
FROM YourTable
GROUP BY ID, Name
You may try with this
DECLARE #T TABLE(ID INT, NAME VARCHAR(50),DATE DATETIME)
INSERT INTO #T VALUES(1,'A','2014-04-20'),(1,'A','2014-04-28')
,(2,'A2','2014-04-22'),(2,'A2','2014-04-24')
,(3,'A3','2014-04-20'),(3,'A3','2014-04-28')
,(4,'A4','2014-04-28'),(4,'A4','2014-04-28')
,(5,'A5','2014-04-28'),(5,'A5','2014-04-28')
SELECT T.ID FROM #T T
WHERE T.DATE=(SELECT MAX(A.DATE)
FROM #T A
WHERE A.ID=T.ID
GROUP BY A.ID )
GROUP BY T.ID
select id, max(date) from NameOfYourTable group by id;

Select the first instance of a record

I have a table, myTable that has two fields in it ID and patientID. The same patientID can be in the table more than once with a different ID. How can I make sure that I get only ONE instance of every patientID.?
EDIT: I know this isn't perfect design, but I need to get some info out of the database and today and then fix it later.
You could use a CTE with ROW_NUMBER function:
WITH CTE AS(
SELECT myTable.*
, RN = ROW_NUMBER()OVER(PARTITION BY patientID ORDER BY ID)
FROM myTable
)
SELECT * FROM CTE
WHERE RN = 1
It sounds like you're looking for DISTINCT:
SELECT DISTINCT patientID FROM myTable
you can get the same "effect" with GROUP BY:
SELECT patientID FROM myTable GROUP BY patientID
The simple way would be to add LIMIT 1 to the end of your query. This will ensure only a single row is returned in the result set.
WITH CTE AS
(
SELECT tableName.*,ROW_NUMBER() OVER(PARTITION BY patientID ORDER BY patientID) As 'Position' FROM tableName
)
SELECT * FROM CTE
WHERE
Position = 1

SQL How to Select the most recent date item

Hello I have a table with columns:
*using oracle
ID NUMBER
USER_ID NUMBER
DATE_ADDED DATE
DATE_VIEWED DATE
DOCUMENT_ID VARCHAR2
URL VARCHAR2
DOCUMENT_TITLE VARCHAR2
DOCUMENT_DATE DATE
I want to know how i can get the most recently added document for a given user.
Select * FROM test_table WHERE user_id = value AND (do something with date_added column)
Thanks
Select *
FROM test_table
WHERE user_id = value
AND date_added = (select max(date_added)
from test_table
where user_id = value)
Not sure of exact syntax (you use varchar2 type which means not SQL Server hence TOP) but you can use the LIMIT keyword for MySQL:
Select * FROM test_table WHERE user_id = value
ORDER BY DATE_ADDED DESC LIMIT 1
Or rownum in Oracle
SELECT * FROM
(Select rownum as rnum, * FROM test_table WHERE user_id = value ORDER BY DATE_ADDED DESC)
WHERE rnum = 1
If DB2, I'm not sure whether it's TOP, LIMIT or rownum...
With SQL Server try:
SELECT TOP 1 *
FROM dbo.youTable
WHERE user_id = 'userid'
ORDER BY date_added desc
You haven't specified what the query should return if more than one document is added at the same time, so this query assumes you want all of them returned:
SELECT t.ID,
t.USER_ID,
t.DATE_ADDED,
t.DATE_VIEWED,
t.DOCUMENT_ID,
t.URL,
t.DOCUMENT_TITLE,
t.DOCUMENT_DATE
FROM (
SELECT test_table.*,
RANK()
OVER (ORDER BY DOCUMENT_DATE DESC) AS the_rank
FROM test_table
WHERE user_id = value
)
WHERE the_rank = 1;
This query will only make one pass through the data.
Assuming your RDBMS know window functions and CTE and USER_ID is the patient's id:
WITH TT AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY USER_ID ORDER BY DOCUMENT_DATE DESC) AS N
FROM test_table
)
SELECT *
FROM TT
WHERE N = 1;
I assumed you wanted to sort by DOCUMENT_DATE, you can easily change that if wanted. If your RDBMS doesn't know window functions, you'll have to do a join :
SELECT *
FROM test_table T1
INNER JOIN (SELECT USER_ID, MAX(DOCUMENT_DATE) AS maxDate
FROM test_table
GROUP BY USER_ID) T2
ON T1.USER_ID = T2.USER_ID
AND T1.DOCUMENT_DATE = T2.maxDate;
It would be good to tell us what your RDBMS is though. And this query selects the most recent date for every patient, you can add a condition for a given patient.
Select Top 1* FROM test_table WHERE user_id = value order by Date_Added Desc