Ordering MySQL Query By Random and a Field? - sql

I am trying to find a way to pull 10 random records and then order those 10 records by a field. I have tried the following:
SELECT name FROM users ORDER BY RAND(), name LIMIT 10
but it does not order by name with 10 rows returned, just return 10 random record in any order. Is there a way to order by rand() and a field within a query with MySQL?

SELECT name
FROM (
SELECT name
FROM users
ORDER BY
RAND()
LIMIT 10
) q
ORDER BY
name

Ended up just doing the sort in php.

Related

How to delete the X oldest items in a table in Postgres?

I'm trying to implement a rolling version system, where users can make keep several versions of something, but once it goes past 10 versions, it deletes the oldest item(s).
This is what I want to do, but the syntax is invalid (can't use the row count in LIMIT):
with version_ids as (
select rd.id from reels_data rd, reels r where r.owner_id = '7f92dcc6-f906-418a-aee0-074b297bfb52' and reel_id = 40 order by version
)
delete from reels_data where id in (select id, count(*) as rows from version_ids limit 10 - rows);
There's still a lot I don't know about Postgres, so I imagine there's some better way to do this.
If I understood the question correctly, you could list the existinɡ versions for a user in descending order, skip the first 10 (i.e the 10 latest) and delete the rest:
DELETE FROM reels_data
WHERE id IN (
SELECT id
FROM reels
WHERE reels.owner_id = '7f92dcc6-f906-418a-aee0-074b297bfb52'
ORDER BY version DESC /* assuming no null versions */
OFFSET 10
)
If a user has less than 10 versions, the OFFSET will make it so nothing is returned (and deleted).
If you're looking to do this for multiple users in a single query you'll need to use a window function (presumably rank() or row_number()).
If you want to just keep the 10 newer :
Select the 10 newer's ids by ordering by version and using LIMIT
Delete all from your table where id not in what you selected
I think you want:
delete from reels_data rd
where rd.id < (select rd2.id
from reels_data rd2
where rd2.owner = rd.owner
order by rd2.id desc
limit 1 offset 9
);
The subquery gets the 10th largest id for each owner. Anything smaller is deleted. If there are not 10, then the subquery returns NULL and nothing gets deleted for that owner.
Much quicker NOT IN than Marth's:
DELETE FROM tableName
WHERE id NOT IN (
SELECT id
FROM tableName
ORDER BY id DESC
LIMIT 10
)

Group by question in SQL Server, migration from MySQL

Failed finding a solution to my problem, would love your help.
~~ Post has been edited to have only one question ~~-
Group by one query while selecting multiple columns.
In MySQL you can simply group by whatever you want, and it will still select all of them, so if for example I wanted to select the newest 100 transactions, grouped by Email (only get the last transaction of a single email)
In MySQL I would do that:
SELECT * FROM db.transactionlog
group by Email
order by TransactionLogId desc
LIMIT 100;
In SQL Server its not possible, googling a bit suggested to specify each column that I want to have with an aggregate as a hack, that couldn't cause a mix of values (mixing columns between the grouped rows)?
For example:
SELECT TOP(100)
Email,
MAX(ResultCode) as 'ResultCode',
MAX(Amount) as 'Amount',
MAX(TransactionLogId) as 'TransactionLogId'
FROM [db].[dbo].[transactionlog]
group by Email
order by TransactionLogId desc
TransactionLogId is the primarykey which is identity , ordering by it to achieve the last inserted.
Just want to know that the ResultCode and Amount that I'll get doing such query will be of the last inserted row, and not the highest of the grouped rows or w/e.
~Edit~
Sample data -
row1:
Email : test#email.com
ResultCode : 100
Amount : 27
TransactionLogId : 1
row2:
Email: test#email.com
ResultCode:50
Amount: 10
TransactionLogId: 2
Using the sample data above, my goal is to get the row details of
TransactionLogId = 2.
but what actual happens is that I get a mixed values of the two, as I do get transactionLogId = 2, but the resultcode and amount of the first row.
How do I avoid that?
Thanks.
You should first find out which is the latest transaction log by each email, then join back against the same table to retrieve the full record:
;WITH MaxTransactionByEmail AS
(
SELECT
Email,
MAX(TransactionLogId) as LatestTransactionLogId
FROM
[db].[dbo].[transactionlog]
group by
Email
)
SELECT
T.*
FROM
[db].[dbo].[transactionlog] AS T
INNER JOIN MaxTransactionByEmail AS M ON T.TransactionLogId = M.LatestTransactionLogId
You are currently getting mixed results because your aggregate functions like MAX() is considering all rows that correspond to a particular value of Email. So the MAX() value for the Amount column between values 10 and 27 is 27, even if the transaction log id is lower.
Another solution is using a ROW_NUMBER() window function to get a row-ranking by each Email, then just picking the first row:
;WITH TransactionsRanking AS
(
SELECT
T.*,
MostRecentTransactionLogRanking = ROW_NUMBER() OVER (
PARTITION BY
T.Email -- Start a different ranking for each different value of Email
ORDER BY
T.TransactionLogId DESC) -- Order the rows by the TransactionLogID descending
FROM
[db].[dbo].[transactionlog] AS T
)
SELECT
T.*
FROM
TransactionsRanking AS T
WHERE
T.MostRecentTransactionLogRanking = 1

Order By clause in sql server

Suppose, there is a table and I need to sort one of its column (name) alphabetically and at the same time I want to sort it by using ID column in asc order based on the condition ( rows that have same name). So, I failed to understand how this will work. Once the records will be sorted by column (name) then will it sort all rows by using id column?
Can someone explain how actually order by clause works in this case
select name,
id
from hack h
order by name,
id
use order by name, id
select name,
id
from hack
order by name,
id
I just tried to understand what you want to know, you want to realize how it happens when the order by clause have two or more columns ,am I right? Let's go to an example,
the first column is id and the second is name,
2 A
5 B
6 A
3 A
1 B
the result of SQL "select name,id from hack order by name,id" will get the result as below
A 2
A 3
A 6
B 1
B 5
see, it will sort first by name column, and then sort id in the same name value group.
That's it ,did I make it clear?
This answers the original question.
In the code you posted:
substring(name, len(name) - 2, len(name))
returns the last 3 characters of the name.
So you are sorting by these last 3 characters and not by name.
When there are 2 names with the same last 3 characters these will be sorted by id.
If there are more than one column names after "order by" keyword, the system orders the records according to the first column just after order by.

Show multiple colums with MAX in sql

I am trying to write a query that shows the names of people with the highest salary in one of my tables.
Currently I have
SELECT MAX (salaris)
FROM (Technischdirecteur);
But this only shows a number and not the corresponding name to it. How would I go about adding the name of the person that has this salary?
Its Simple You can go with this way
And also you can choose the column you want to display by replacing the *
select *
From Technischdirecteur
Where salaris= (Select Max(salaris) From Technischdirecteur)
SELECT a.*, c.name
FROM Technischdirecteur a, club c
(SELECT MAX(salaris) salaris FROM Technischdirecteur) b
WHERE a.salaris = b.salaris
AND a.cl_id = c.cl_id
If you want all the values, don't think MAX(), think ORDER BY:
SELECT td.*
FROM Technischdirecteur td
ORDER BY salary desc
LIMIT 1;
Depending on the database, the LIMIT 1 could be FETCH FIRST 1 ROWS ONLY, TOP 1 (in the SELECT clause`, or even something else.

Make pagination in SQL with sorted records

I have 100 records, and this records contains, username(string) and groupname(string). And I want to sort the whole records by groupname or by username. Is there an SQL query string that I can sort first the whole records then limit the number of records? Or is there any way to do this kind of method?
Many thanks.
try this:
SELECT username, groupname FROM tablename ORDER BY groupname ASC LIMIT 0, 10
This selects both the username and groupname fields and orders them by groupname in Ascending order. Limit is taking two parameters, the starting offset and the number of records to return.
To sort you can try (MS-SQL):
SELECT TOP 10
username, groupname
FROM table
ORDER BY username,groupname
or for MySQL:
SELECT username, groupname
FROM table
ORDER BY username,groupname
LIMIT 0,10
ORDER BY groupname LIMIT 0, 10
where 0 is start and 10 is count of records
SELECT username, groupname FROM table ORDER BY username LIMIT 0, 10
You need some way to pass in the desired sorting preference, such as a variable
DECLARE sort VARCHAR(10);
SET sort = 'group'
SELECT
username, groupname
FROM
tablename
ORDER BY
CASE
WHEN sort = 'group' THEN groupname
WHEN sort = 'user' THEN user
END
LIMIT 0, 10