I have a student_table table with two columns student_name(with uniqe constraint),student_marks. From this table, I need to get the record of the student who has the 3rd highest marks.
I tried this, but it's incorrect:
select * from student_table orderby(marks) enum(marks)=3;
How do I correct this query?
Here is a very simple solution
select *
from marks
order by marks desc
limit 2,1
with limit you can use offset and length. Here offset is set to two because it starts from 0. For third record. And 1 is the limit.
Here is another solution
$res=mysql_query("SELECT * from marks order by marks desc");
mysql_data_seek($res, 2);
$row=mysql_fetch_assoc($res));
Try this
SELECT * FROM `student_table` ORDER BY marks DESC LIMIT 2,1
If you just want the 3rd record:
SELECT * FROM student_table ORDER BY marks DESC LIMIT 2,1
Have a read about the LIMIT command.
In MySQL you can do:
SELECT * FROM Student_Table ORDER BY Marks LIMIT 2, 1
select * from students_table orderby marks limit 2,1
Check this url to more about limit http://php.about.com/od/mysqlcommands/g/Limit_sql.htm
Use Below query
QUERY : select * from student_table where marks in (select marks from student_table group by marks order by marks desc limit 2,1);
The following query will return all records for students in third place, regardless of how many students are tied for first, second, or third place.
SELECT student_table.name, student_table.marks
FROM student_table
WHERE student_table.primary_key IN ( SELECT ranked.primary_key
FROM student_table ranked
LEFT JOIN student_table others
ON ranked.marks < others.marks
GROUP BY 1
HAVING COUNT(DISTINCT others.marks) + 1 = 3)
For example, if student_table looks like this:
+---------+-------+
| name | marks |
+---------+-------+
| Alpha | 100 |
| Able | 100 |
| Bravo | 98 |
| Baker | 98 |
| Bone | 98 |
| Charlie | 93 | <-- 3rd place by marks
| Chimp | 93 | <-- 3rd place by marks
| Delta | 85 |
| Echo | 80 |
| Ebert | 80 |
+---------+-------+
the query will yield:
+---------+-------+
| name | marks |
+---------+-------+
| Charlie | 93 |
| Chimp | 93 |
+---------+-------+
As an aside, the query would be a little easier if MySQL supported DENSE_RANK(), but you can simulate that function with subqueries as above.
Related
This SQL tells me how much when the maximum occurred in the last hour, and is easily modified to show the same for the minimum.
SELECT
mt.mB as Hr_mB_Max,
mt.UTC as Hr_mB_Max_when
FROM
thundersense mt
WHERE
mt.mB =(
SELECT
MAX(mB)
FROM
thundersense mt2
WHERE
mt2.UTC >(UNIX_TIMESTAMP() -3600))
ORDER BY
utc
DESC
LIMIT 1
How do I modify it so it returns both maximum & minimum and their respective times?
Yours Simon M.
Based on my understanding of your question, you are looking to create a 4 column and 1 row answer where it looks like:
+-------+-----------------+----------+-----------------+
| event | time_it_occured | event | time_it_occured |
+-------+-----------------+----------+-----------------+
| fun | 90000 | homework | 12000 |
+-------+-----------------+----------+-----------------+
Below is a similar situation/queries you can adapt for your situation.
So, given a table called 'people' that looks like:
+----+------+--------+
| ID | name | salary |
+----+------+--------+
| 1 | bob | 40000 |
| 2 | cat | 12000 |
| 3 | dude | 50000 |
+----+------+--------+
You can use this query:
SELECT * FROM
(SELECT name, salary FROM people WHERE salary = (SELECT MAX(salary) FROM people)) t JOIN
(SELECT name, salary FROM people WHERE salary = (SELECT MIN(salary) FROM people)) a;
to generate:
+------+--------+------+--------+
| name | salary | name | salary |
+------+--------+------+--------+
| bob | 40000 | cat | 12000 |
+------+--------+------+--------+
Some things to note:
you can change the WHERE clauses to be the ones you have mentioned in question (for MAX and MIN).
Please be careful with the above query, here I am using a cartesian join (cross join in MYSQL) in order to get the 4 columns. To be honest, it doesn't make sense for me to get back data in one row but you said that's what you're looking for.
Here is what I would work with instead, getting two tuples/rows back:
+----------+--------+
| name | salary |
+----------+--------+
| dude | 95000 |
| Cat | 12000 |
+----------+--------+
And to generate this, you would use:
(SELECT name, salary FROM instructor WHERE salary = (SELECT MAX(salary) FROM instructor))
UNION
(SELECT name, salary FROM instructor WHERE salary = (SELECT MIN(salary) FROM instructor));
Also: A JOIN without a ON clause is just a CROSS JOIN.
How to use mysql JOIN without ON condition?
One method uses a join:
SELECT mt.mB as Hr_mB_Max, mt.UTC as Hr_mB_Max_when
FROM thundersense mt JOIN
(SELECT MAX(mB) as max_mb, MIN(mb) as min_mb
FROM thundersense mt2
WHERE mt2.UTC >(UNIX_TIMESTAMP() - 3600)
) mm
ON mt.mB IN (mm.max_mb, mm.min_mb)
ORDER BY utc DESC;
My only concern is your limit 1. Presumably, the mBs should be unique. If not, there is a bit of a challenge. One possibility would be to use an auto-incremented id rather than mB.
feedback table
-------------------------------
|rating|feedback|feedback_date|
-------------------------------
| 5 | good | 1452638788 |
| 1 | bad | 1452638900 |
| 0 | ugly | 1452750303 |
| 3 | ok | 1453903030 |
-------------------------------
desired result
average_rating | rating | feedback | feedback_date
2.25 | 3 | ok | 1453903030
Is it possible (in a single query) to select the average of one column and also one specific row from the table?
For example, i'd like to retrieve the average of the column rating and the most recent row as a whole.
I tried the following, and also with the ORDER BY direction as DSC but they both just gave me the average_rating and the first row in the table.
SELECT AVG(f.rating) AS average_rating, f.* FROM feedback f ORDER BY feedback_date ASC
SELECT * FROM feedback NATURAL JOIN (
SELECT AVG(rating), MAX(feedback_date) feedback_date FROM feedback
) t
See it on sqlfiddle.
you can do it with a sub query like this
SELECT AVG(f.rating) AS average_rating, t1.* FROM feedback f inner join (select * from feedback order by feedback_date asc limit 1 ) t1 on true
You can put a subquery in the SELECT clause, and calculate the average in the subquery.
SELECT (SELECT AVG(rating) FROM feedback) AS avg_rating, feedback.*
FROM feedback
ORDER BY feedback_date DESC
LIMIT 1
I have a leader board of high scores and need to not show the duplicate records for a more accurate leader board.
Table: highscores
+-------------------+----------------+-------------+-------+
| id | name | time | moves | score |
+-------------------+----------------+-------------+-------+
| 1 | person1 | 33 | 22 | 245 |
+-------------------+----------------+-------------+-------+
| 2 | person1 | 83 | 31 | 186 |
+-------------------+----------------+-------------+-------+
and my query is
SELECT * FROM highscores ORDER by Score DESC LIMIT 100
how can I change the query to only show the higherscore of duplicate records without messing up the descending part
this seems to be working
SELECT * FROM highscores GROUP BY name ORDER by Score DESC LIMIT 100
Use mysql's custom group by:
SELECT * FROM (
SELECT * FROM highscores
ORDER by Score DESC) x
GROUP BY name
ORDER by Score DESC
LIMIT 100
This works because when not all non-aggregate columns are listed in the group by, mysql returns the first row encountered for each unique combination of the columns listed in the group by.
Ok so its easier to give an example and hopefully some has a solution:
I have table that holds bids:
ID | companyID | userID | contractID | bidAmount | dateAdded
Below is an example set of rows that could be in the table:
ID | companyID | userID | contractID | bidAmount | dateAdded
--------------------------------------------------------------
10 | 2 | 1 | 94 | 1.50 | 1309933407
9 | 2 | 1 | 95 | 1.99 | 1309933397
8 | 2 | 1 | 96 | 1.99 | 1309933394
11 | 103 | 1210 | 96 | 1.98 | 1309947237
12 | 2 | 1 | 96 | 1.97 | 1309947252
Ok so what I would like to do is to be able to get all the info (like by using * in a normal select statement) the lowest bid for each unique contractID.
So I would need the following rows:
ID = 10 (for contractID = 94)
ID = 9 (for contractID - 95)
ID = 12 (for contractID = 96)
I want to ignore all the others. I thought about using DISTINCT, but i haven't been able to get it to return all the columns, only the column I'm using for distinct.
Does anyone have any suggestions?
Thanks,
Jeff
select *
from mytable main
where bidAmount = (
select min(bidAmount)
from mytable
where contractID = main.contractID)
Note that this will return multiple rows if there is more than one record sharing the same minimum bid.
Didn't test it but it should be possible with this query although it might not be really fast:
SELECT * FROM bids WHERE ID IN (
SELECT ID FROM bids GROUP BY contractID ORDER BY MIN(bidAmount) ASC
)
This would be the query for MySQL, maybe you need to adjust it for another db.
You could use a subquery to find the lowest rowid per contractid:
select *
from YourTable
where id in
(
select min(id)
from YourTable
group by
ContractID
)
The problem is that distinct does not return a specific row - it return distinct values, which ( by definition ) could occur on multiple rows.
Subqueries are your answer, and somewhere in the suggestions above is probably the answer. Your subquery need to return the ids or the rows with the minimum bidvalue. Then you can select * from the rows with those ids.
I have a table like this:
id | name | class | marks
1 | abc | 1 | 90
2 | cdf | 1 | 100
3 | xyz | 1 | 70
I want to get 2nd highest marks record. How can I get it with with one query. Simple and short?
SELECT * FROM `tableName` ORDER BY `marks` DESC LIMIT 1,1
Use LIMIT and ORDER
SELECT * FROM table
ORDER BY marks DESC LIMIT 1,1
ORDER BY marks DESC means: descending ordering, so highest on top.
LIMIT 1,1 means offset = 1 and only select 1 row.