Ordering the SQL query in a particular order - php

Say i have a table Guest and it has column g_id : values 1 to 10.
Now i want the query to return me the g_id's neither in ascending order nor in descending..
but i want the 4th then 3rd and then 5th entry, in this particular order.
Also i want just the 4th 3rd and 5th entry.
say my entries have an id and a name . ;i.e. my table Guest has these two tables.
Now my table is as following.
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
10 J
Now i want just the entry with 4th 3rd and 5th g_id, and in this particular order.
How do i write the SQL query?
Thanks.
Select * from Guest ___________???
Kindly fill in the gaps.

You can use a CASE statement in your ORDER BY to use a fake column to sort on and a WHERE IN clause to only return the values you need.
SELECT *
FROM Guest
WHERE g_id IN (3, 4, 5)
ORDER BY
CASE WHEN g_id = 4 THEN 1
WHEN g_id = 3 THEN 2
WHEN g_id = 5 THEN 3
END

What is the order that deteremines whether something is 4th, 3rd or 5th? Without an ORDER BY clause, the data is returned in an indeterminate order by SQL. You cannot rely on the order that rows are entered or stored in the database table itself.
You can hard-code what you are asking like this:
select *
from Guest
order by case
when g_id = 4 then 1
when g_id = 3 then 2
when g_id = 5 then 3
else 4
end

One solution is the case statement:
select g_id from (
select g_id, case g_id
when 4 then 1
when 3 then 2
when 5 then 3
else 0
end virtcol
where virtcol != 0
order by virtcol
);

I'm not sure how set your ordering will be, but you can order by specifics:
ORDER BY
g_id = 4 DESC,
g_id = 3 DESC,
g_id = 5 DESC
You may be better off selecting the entries as they are and doing something like this in your php code:
$order = array('4 ', '3 ', '5 ');
$data = array();
while ($row = $result->fetch()) {
$data["$row->g_id "] = $row;
}
$data = array_merge(array_flip($order), $data);

I think that the answer mostly depends on the DBMS you are working on.
In Oracle the query below, even though inefficient, should work
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 4
UNION
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 3
UNION
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 5
Not sure if something of more efficient is possible with a simple query,
i would use the monster above only and only if the table you are querying is very small.
You also have another option if the table is big and you have to extract only the first rows. In the case you described, I would retrieve the first 5 rows and then programmatically I would extract the rows in position 4,3,5.
you can extract the first 5 rows with this query in oracle
select * from guest order by id asc where rownum < 6

This query will get you the 3rd, 5th, and 4th items (limit 2, 1 means "retrieve starting with 3rd item, with total number retrieved = 1 records)
(select g_id from Guest limit 2,1)
UNION (select g_id from Guest limit 4,1
UNION (select g_id from Guest limit 3,1)

Related

how to get a sql rank query working to find the rank of a specific id

I try to do a rank query but i fail to get it working correctly. The rank is calculated by the highest market_cap followed by the highest id in case the market_cap has the same value, the condition active must be 1. I only want the rank of a specific id in the end.
Table:
id
market_cap
active
expected rank
1
67000
1
4
2
197000
1
1
3
67000
1
3
4
127000
1
2
5
17000
1
5
6
37000
1
5
7
2237000
0
/
This is the PHP(Laravel) code that does exactly that and is working, but i want to use it as plain SQL for speed improvements since my table has 20k rows.
$token_list = DB::table('tokens')->where('active', 1)->orderBy('market_cap', 'desc')->orderBy('id', 'desc')->get(array('id'));
foreach($token_list as $key => $token){
if($token->id == $data['token']->id){
$token_rank = $key+1;
}
}
Current Query that is not working yet (it stops to work for all results that have a market_cap of 0, which are thousands, they all get the same ranking which is the last rank number):
$rank_query = DB::select("SELECT FIND_IN_SET(market_cap, ( SELECT GROUP_CONCAT(market_cap ORDER BY market_cap DESC, id DESC) FROM tokens WHERE active = 1)) AS rank FROM tokens WHERE id = {$data['token']->id}");
$token_rank = $rank_query[0]->rank;
In a SQL query, you can use row_number():
select t.*
from (select t.*,
(case when active
then row_number() over (partition by active order by market_cap desc, id desc)
end) as ranking
from t
) t
where . . .
You would put your filtering conditions in the outer query.
You can do something like this with Laravel's query builder as well. There's no need to use raw sql.
$marketCapQuery = DB::table('tokens')->selectRaw('GROUP_CONCAT(market_cap ORDER BY market_cap DESC, id DESC)'->where('active', 1)->toSql();
$rank_query = DB::table('tokens')->selectRaw("FIND_IN_SET(market_cap, ( '.$marketCapQuery.') AS rank'->where('id', $data['token']->id);
$token_rank = $rank_query[0]->rank;

How select next row pagination in sql

I'm sorry I'm weak for English.
i echo 2 row in each page . how echo next 2 row
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category
WHERE mzmx_post.id = mzmx_post_category.post_id AND zmx_post_category.category_id = 5
ORDER BY id DESC
LIMIT 2
You can use the two-arguments form of LIMIT to offset the result by a given number of rows, like:
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category ON mzmx_post.id = mzmx_post_category.post_id
WHERE mzmx_post_category.category_id = 5
ORDER BY id DESC
LIMIT 2, 2 -- fetch records 3 and 4
This gives you the second page. If you want the third page, then:
LIMIT 4, 2
And so on.
Note that I modified your query so the joining condition between the tables is placed in the ON clause of the join rather than in the WHERE clause.
Better add one extra column (e.g. mzmx_post_key bigint) of Long type in each table and have sequential value on that column. Use that column to fetch data from DB from page wise.
sqL suery should look like:
SELECT *
FROM `mzmx_post`
JOIN mzmx_post_category ON mzmx_post.id = mzmx_post_category.post_id
WHERE mzmx_post_category.category_id = 5 and mzmx_post_key> ##last record key##
ORDER BY mzmx_post_key ASC
LIMIT 2
The basic idea is to use
LIMIT n,o
where n is the results per page
o is the offset from the first result
for the p-th page the offset would be
o = p * n
where p = 0,1,2,....

SQL multi order

Assume this array is my db table.
array('1','1','1','2','2','2','3','3','3','4','4','4','4','5','5','5','5');
in that table i have status from 1 to 5. but i want get data first with status = 2,sec 5 ... ,1,3,4.
is it possible ? if not how can i do it with php.
You may order using FIELD:
SELECT *
FROM yourTable
ORDER BY FIELD(status,2,5,1,3,4);
Demo
If you get the array from a table then you could use a CASE WHEN in the ORDER BY of your query
For example:
select num
from YourTable
order by (case when num = 2 then 1 when num = 5 then 2 else num+2 end);

select mysql from a row limit and asc php pdo

I have a table like below
ID
1
2
3
4
5
I want to select ID 2 then ASC LIMIT 3. I want to get 2,3,4.
My select goes.
SELECT * FROM TABLEID WHERE ID = 2 AND status = 'unuse' ORDER BY ID ASC LIMIT 3
But I only get 1 record I am expecting 3 row to be returned base on the LIMIT 3
I am expecting 3 row to be returned base on the LIMIT 3
You are expecting wrong, because LIMIT can not create records that aren’t there to begin with. You have only one record with ID=2, so a WHERE clause selecting those records of course only returns this one.
You want WHERE ID >= 2 to first select all records that have an id 2 or greater, and then limit that selection to 3 records only.
select * from TABLED limit 1,4
1 is offset start point
4 is upto count point
SELECT * FROM TABLEID WHERE ID BETWEEN 2 AND 4
OR exclude the id
SELECT * FROM TABLEID WHERE ID >=2 status = 'unuse' AND id <> 1 ORDER BY ID ASC LIMIT 3

Update field if the ORDER BY is 1 descending?

Is there a possible way to do this:
I want to update a field 'rank' according to the ORDER BY place.
For example: (pseudocode)
If id order by place = 1 then update rank field to place were id=get id
rank place id
1 1 5 PC
2 2 8 MAC
is this possible?
Something like this?
UPDATE tbl_name
SET rank = 1
WHERE id = (
SELECT id
WHERE condition
ORDER BY place DESC
LIMIT 1
)
Or from your comment (I think MySQL http://dev.mysql.com/doc/refman/5.0/en/update.html):
UPDATE tbl_name
SET rank = 10
WHERE id = 9
ORDER BY wins DESC
LIMIT 1
You can always do a SELECT to check if these are the records you wish to UPDATE as well:
SELECT *
FROM tbl_name
WHERE id = (
SELECT id
WHERE condition
ORDER BY place DESC
LIMIT 1
)
OR
SELECT *
FROM tbl_name
WHERE id = 9
ORDER BY wins DESC
LIMIT 1
Some RDBMS have a ROWNUM pseudocolumn in queries you can use for this.
You did not specify what database you are using, for example Oracle has this.

Categories