How to do this query to select N rows with highest numbers ordered by col - sql

Lets say I have a table that has three columns: ID, Name and Users.
I want to select the 3 rows with the highest number of users and I wanted the rows to be ordered by the Name Ascending. How can I Achieve that?
I used
select Name from TABLE where ID IN (select ID from Tablesorder by Users desc limit 3)
But IN/ANY are not supported. Any other ways?
Thanks

When subqueries are allowed, you could use this.
It fetches the 3 records with highest value for column users. These 3 results will be ordered in the outer query.
select Name from
(
select Name
from Tables
order by Users desc
limit 3
) as temp
ORDER BY Name ASC

In Mysql :
SELECT id, name, users
FROM (SELECT id,name,users FROM tablename ORDER BY users DESC LIMIT 3) as a
ORDER BY name;
In Sql server
SELECT id, name, users
FROM (SELECT TOP 3 id,name,users FROM tablename ORDER BY users DESC ) as a
ORDER BY name;
In Oracle
SELECT id, name, users
FROM (SELECT id,name,users FROM tablename ORDER BY users DESC ) as a
WHERE ROWNUM<=3
ORDER BY name;

Related

COUNT of GROUP of two fields in SQL Query -- Postgres

I have a table in postgres with 2 fields: they are columns of ids of users who have looked at some data, under two conditions:
viewee viewer
------ ------
93024 66994
93156 93151
93163 113671
137340 93161
92992 93161
93161 93135
93156 93024
And I want to group them by both viewee and viewer field, and count the number of occurrences, and return that count
from high to low:
id count
------ -----
93161 3
93156 2
93024 2
137340 1
66994 1
92992 1
93135 1
93151 1
93163 1
I have been running two queries, one for each column, and then combining the results in my JavaScript application code. My query for one field is...
SELECT "viewer",
COUNT("viewer")
FROM "public"."friend_currentfriend"
GROUP BY "viewer"
ORDER BY count DESC;
How would I rewrite this query to handle both fields at once?
You can combine to columns from the table into a single one by using union all then use group by as below:
select id ,count(*) Count from (
select viewee id from vv
union all
select viewer id from vv) t
group by id
order by count(*) desc
Results:
This is a good place to use a lateral join:
select v.viewx, count(*)
from t cross join lateral
(values (t.viewee), (t.viewer)) v(viewx)
group by v.viewx
order by count(*) desc;
You can try this :
SELECT a.ID,
SUM(a.Total) as Total
FROM (SELECT t.Viewee AS ID,
COUNT(t.Viewee) AS Total
FROM #Temp t
GROUP BY t.Viewee
UNION
SELECT t.Viewer AS ID,
COUNT(t.Viewer) AS Total
FROM #Temp t
GROUP BY t.Viewer
) a
GROUP BY a.ID
ORDER BY SUM(a.Total) DESC

how to select the most recent records

Select id, name , max(modify_time)
from customer
group by id, name
but I get all records.
Order by modify_time desc and use row_number to number the row for id,name combination.Then select each combination with row_number = 1
select id,modify_time,name
from (
select id,modify_time,name,row_number() over(partition by id order by modify_time desc) as r_no
from customer
) a
where a.r_no=1
Ids are unique, which means grouping them by the id, will result in the same table.
My suggestion would be, to order the table by "modify_time" descending and limit the result to 1 (Maybe something like the following):
Select id, name modify_time from customer ORDER BY modify_time DESC limit 1
The reason you are getting the whole table as a result is because you are grouping by id AND name. That means every unique combination of id and name is returned. And since all names per id are different, the whole table is returned.
If you want the last modification per id (or name) you should only group by id (or name respectively).

Select a row with preceding and following rows

I have a table as follows:
CREATE TABLE results (
id uuid primary key UNIQUE,
score integer NOT NULL
)
I need to select a record with particular UUID and what's around it (say, 5 before and after) ordered by score
SELECT * FROM results
WHERE id = <SOME_UUID>
ORDERED BY score
OFFSET -5 LIMIT 10; -- apparently this is wrong
How can I effectively do that?
Its not 'effective', but you could try this:
select a.* from (SELECT * FROM results
WHERE id <> <SOME_UUID> and score <= (select score from results WHERE id = <SOME_UUID>)
ORDERED BY score,id desc
LIMIT 5) as a
UNION ALL
SELECT * FROM results
WHERE id = <SOME_UUID>
UNION ALL
select b.* from (SELECT * FROM results
WHERE id <> <SOME_UUID> and score >= (select score from results WHERE id = <SOME_UUID>)
ORDERED BY score, id asc
LIMIT 5) as b
I tried this an SQL-Server, which needded the 'ALL' to compute.
So you may get records with equal score as duplicates. To avoid this make it again to a subquery and use select distinct.
One way of solving this is with a rank for each row assigned using a window function and then finding out which ranks you are interested in:
WITH ranked AS (
SELECT id, score, rank() OVER (ORDER BY score) AS rnk
FROM results),
this_rank AS (
SELECT rnk - 5 AS low_rnk FROM ranked
WHERE id = <some uuid>::uuid)
SELECT id, score
FROM ranked, this_rank
WHERE rnk >= low_rnk
ORDER BY rnk
LIMIT 11;
For very low or high scores you get fewer than 11 rows, rather than rows with NULLs.
SQLFiddle
One further detail: A PRIMARY KEY already implies uniqueness so you do not have to use the UNIQUE clause in your table definition.

Row with the highest ID

You have three fields ID, Date and Total. Your table contains multiple rows for the same day which is valid data however for reporting purpose you need to show only one row per day. The row with the highest ID per day should be returned the rest should be hidden from users (not returned).
To better picture the question below is sample data and sample output:
ID, Date, Total
1, 2011-12-22, 50
2, 2011-12-22, 150
The correct result is:
2, 2012-12-22, 150
The correct output is single row for 2011-12-22 date and this row was chosen because it has the highest ID (2>1)
Assuming that you have a database that supports window functions, and that the date column is indeed just date (and not datetime), then something like:
SELECT
* --TODO - Pick columns
FROM
(
SELECT ID,[Date],Total,ROW_NUMBER() OVER (PARTITION BY [Date] ORDER BY ID desc) rn
FROM [Table]
) t
WHERE
rn = 1
Should produce one row per day - and the selected row for any given day is that with the highest ID value.
SELECT *
FROM table
WHERE ID IN ( SELECT MAX(ID)
FROM table
GROUP BY Date )
This will work.
SELECT *
FROM tableName a
INNER JOIN
(
SELECT `DATE`, MAX(ID) maxID
FROM tableName
GROUP BY `DATE`
) b ON a.id = b.MaxID AND
a.`date` = b.`date`
SQLFiddle Demo
Probably
SELECT * FROM your_table ORDER BY ID DESC LIMIT 1
Select MAX(ID),Data,Total from foo
for MySQL
Another simple way is
SELECT TOP 1 * FROM YourTable ORDER BY ID DESC
And, I think this is the most simple way!
SELECT * FROM TABLE_SUM S WHERE S.ID =
(
SELECT MAX(ID) FROM TABLE_SUM
WHERE CDATE = GG.CDATE
GROUP BY CDATE
)

Select records older than latest 100 records from database

My issue here is that i want to populate all the records except latest 100 records in the database. What could be the best approach to accomplish this?
Try using limit cause
SELECT *
FROM Table
order by id desc
limit 101 , totalrecords
Here id is auto increment field of your table
How about something like
SELECT t.*
FROM Table t LEFT JOIN
(
SELECT ID
FROM Table
ORDER BY ID DESC
LIMIT 100
) top100 ON t.ID = top100.ID
WHERE top100.ID IS NULL
Where ID would be the column to identify the order (latest) and Table from where you wish to select
SELECT *
FROM Table
WHERE ID < (SELECT ID
FROM Table
ORDER BY ID DESC
LIMIT 99, 1)