Get first row in Oracle Sql - sql

I am trying to get only the first row from this query. The query does not return the top row. Here is the query.
SELECT DISTINCT name, age
FROM donates, persons
WHERE name = donor
AND name IN (SELECT receiver FROM donates)
AND ROWNUM <= 1
ORDER BY age DESC;
When I run the query it returns Chirs |35.
Without the ROWNUM <=1 this is what the table looks like.
NAME | AGE
-------------
george | 62
Chris | 35
zara | 24

I think the best way to get this is to use a subquery as the rownum is being looked at before the order by so:
select * from (
SELECT DISTINCT name, age
FROM donates, persons
WHERE name = donor
AND name IN (SELECT receiver FROM donates)
ORDER BY age DESC
) where ROWNUM <= 1;
For a longer read look at http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

Try to use ROWID rather than ROWNUM like this:
SELECT * FROM TABLE_NAME WHERE ROWID = (SELECT MIN(ROWID) FROM TABLE_NAME)

You are trying to get the one with minimal age, so I suggest you to use the Min sql built-in function:
SELECT name, Min(age)
FROM donates, persons
WHERE name = donor
AND name IN (SELECT receiver FROM donates)
It is a good practice to avoid rownum. And here you get a more semantic and efficient query.
Hope it helps,
Regards

Related

How can i do it in single SQL?

I have this Table like this
ID | NAME | AGE | ADDRESS | SALARY
and an ID (2)
AGE of ID 2 is 25,
Now i need to count total number of record with AGE 25. How can i do it in single SQL Query? is there any why?
i currently doing it in 2 query. in one i return AGE with ID.
select AGE from table_name where ID = 2
it return AGE 25
and 2nd query i count number of record with this AGE.
select COUNT(*) from table_name where age =25
i want to do it in one SQL Query. is there any way ?
use SQL COUNT function
select COUNT(*) from mytable where age =25
You want to count the number of rows with the same age as the specified ID?
You can use a windowed count
select Agecount
from (
select *, Count(*) over (partition by Age) Agecount
from YourTable
)t
where id=?
Use Group by with subquery
SELECT COUNT(*) AS ageCount
FROM table_name
WHERE age in (SELECT age FROM table_name WHERE ID = 2)
GROUP BY age
For Questions like this the best way is use multiple conditions using Where keyword with And-Or Operators.
This query should work for your requirement without complicating anything.
select count(*) from table_name where ID=2 and age=25;

Stuck to select maximum row

I have a table with columns:
ID | FULLNAME | VALUE
01 Joseph 10
02 Sam 50
... ... ...
I need to select row with maximum value, and show info like
FULLNAME | VALUE
I tried using group function MAX(), but I can't select fullname, because if I use it as a GROUP BY expression, it will select max in groups.
Other way, is to use WITH statement, order table by value desc, use
rank() OVER (PARTITION BY ID) AS max_id
function and maximum value will be on max_id = 1, and then use
WHERE max_id = 1
to remove other rows.
But I think there is a way to do this better and I can't find one.
UPDATE:
A tricky solution to this problem is
SELECT *
FROM t t1
LEFT JOIN t t2 ON t1.value<t2.value
WHERE t2.value IS NULL
The simplest way is to sort the data and pull one row:
select t.*
from t
order by value desc
fetch first 1 row only;
If you want ties, you can add with ties to the fetch first.
Another method is:
select t.*
from t
where t.value = (select max(t2.value) from t t2);
This can have very good performance with an index on value.

Unable to find Max Age of a Player

i am a newbie to SQL.
I wanna find out what which player is oldest by age.
So here is my table..
Somehow my Query give error.
Can you please tell me where i am doing it wrong.
Thanks.
select * from players
where age = (select max(age) as Oldest_Player from players);
limit 1
SQL has a SELECT TOP command, which allows you to retrieve a set number of rows. You can do SELECT TOP 1 name AS 'Oldest Person' FROM players ORDER BY age DESC
What this will do is: first retrieve all the players, sort them by age descending (oldest first), then take the first one.
You can use row_number as below:
Select * from (
Select *, RowN = Row_Number() over(order by age desc) from Players
) a Where a.RowN = 1

query optimization (nested subqueries)

I try to simplify below subqueries to improve select statement. I have table with 3 basic columns as ID, GRAGE and AGE. To select all records which have GRADE same as GRADE of Maximum ID
Might somebody have better way that create nested subqueries, welcome all your suggestions?
Note: My apologise for formatting the table
ID GRADE AGE
10 A 30
12 B 45
13 A 15
09 B 14
20 A 12
SELECT
*
FROM
TABLE
WHERE
GRADE = (
SELECT
grade
FROM
TABLE
WHERE
id = (SELECT MAX(id) FROM TABLE)
);
You could use a CTE to make the query easier to read:
WITH cte AS
(
SELECT GRADE,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID DESC) RowNum
FROM yourTable
)
SELECT *
FROM yourTable
WHERE GRADE = (SELECT t.GRADE FROM cte t WHERE t.RowNum = 1)
However, I don't have a problem with your original approach because the subqueries are not correlated to anything. What I mean by this is that
SELECT MAX(id) FROM yourTable
should effectively only be executed once, and afterwards sort of be treated as a constant. Similarly, the query
SELECT grade FROM TABLE WHERE id = (max from above query)
should also be executed only once. This assumes that the query optimizer is smart enough to figure this out, which it probably is.
You can do the following (not much simpler though):
SELECT
*
FROM
TABLE
WHERE
GRADE IN (
SELECT
first_value (GRADE) over (ORDER BY id DESC)
FROM
TABLE
)

SQL query to select most recent of duplicates

I have a table of values, with a date stored against each entry for example
Name
Age
PaymentAmount
Date
Can someone help me to write a query that would show the most recent payment only of any person within a certain age range.
E.g If I had 5 entries, and wanted the most recent payment of all people aged 20-25
Allan, 45, $1500, 1/1/2014
Tim, 22, $1500, 1/2/2001
John, 25, $2000, 2/3/2001
Tim, 22, $2500, 1/2/2010
John, 25, $3000, 2/3/2010
It would return the bottom 2 rows only
You didn't state your DBMS, so this is ANSI SQL
select *
from (
select name,
age,
PaymentAmount,
Date,
row_number() over (partition by name order by date desc) as rn
from the_table
where age between 22 and 25
) t
where rn = 1;
Another option is to use a co-related subquery:
select name,age,paymentamount,date
from the_table t1
where age between 22 and 25
and date = (select max(date)
from the_table t2
where t2.name = t1.name
and t2.age between 22 and 25)
order by name;
Usually the solution with a window function is faster than the co-related subquery as only a single access to the table is needed.
SQLFiddle: http://sqlfiddle.com/#!15/17e37/4
Btw: having a column named age is a bit suspicious because you need to update that every year. You should rather store the date of birth and then calculate the age when retrieving the data.
This query would give you all records of most recent payment of age 20 and 25. Limit it by using TOP 2 or LIMIT 2 or rownum <=2 as per your DB syntax
SELECT NAME,AGE,PAYMENTAMOUNT,DATE FROM MY_TABLE
WHERE AGE BETWEEN 20 AND 25
AND DATE IN
(
SELECT MAX(DATE)
FROM MY_TABLE
WHERE
AGE BETWEEN 20 AND 25
);
EDIT as per horse_with_no_name:
SELECT NAME,AGE,PAYMENTAMOUNT,DATE
FROM the_table
WHERE AGE BETWEEN 20 AND 25
AND DATE IN
(
SELECT (DATE)
FROM the_table
WHERE
AGE BETWEEN 20 AND 25 order by date desc limit 2
)
limit 2;
Fiddle reference : http://sqlfiddle.com/#!15/17e37/10
Simplest of all,Try this following query
select name,age,paymentamount,date from yourtablename where date in (select max(date) from yourtablename where age between 20 and 25 and group by name);
You should Create a Table with Identity Column to make your Life easier
ColumnPrimaryKey IDENTITY (1,1)
Name
Age
PaymentAmount
Date
SELECT TOP 2 * FROM [TableName] Where Age BETWEEN 20 AND 25 ORDER BY [PrimaryKey] DESC
The above query will return the top two row Inserted in table
You can use between like
select * from meta where title='$title' and (date between '$start_date' and '$end_date').
Okay, I know you said SQL-- here's for people with two layers.
VIA SQL:
Order your SQL results by date descending (should be newest to oldest...).
VIA YOUR "BACK END":
Create an empty final set.
As you are iterating through your results, if your result row person is not in your final set, add the data to the final set.
Boom, your final set has the latest of each person.