mysql - order by field not working properly - php

suppose I've a database , the table contains rows with ides from 1 to 20 .
i want to return 3 rows with id 3,4,1 first and then return the other rows . this is my code :
SELECT id
FROM prod
ORDER BY field( id, 3, 4, 1 )
LIMIT 20
this is the result of this code :
id
13
17
16
15
7
6
5
2
3
4
1
strangely the 3 rows that I need to come first are showing at the end ,
How can I bring these 3 rows to the top of the list ?
Thanks

You can use DESC:
SELECT id
FROM prod
ORDER BY field( id, 3, 4, 1 ) DESC
LIMIT 20
The issue is that MySQL puts NULL values first when you do an ascending order by.
If you actually want the rows in the order 3, 4, 1, then reverse them in the field statement:
SELECT id
FROM prod
ORDER BY field( id, 1, 4, 3 ) DESC
LIMIT 20
Or, if you wanted to be fancy:
ORDER BY - field( id, 3, 4, 1 ) DESC

The other way is to use case-when and giving each id an order value
select * from prod
order by
case
when id = 3 then 0
when id=4 then 1
when id=1 then 2
else 3
end,id
limit 20
;

Try with DESC
SELECT id
FROM prod
ORDER BY field( id, 3, 4, 1 ) DESC
LIMIT 20
It seems your id order is important. Reverse numbers to get correct result
SELECT id
FROM prod
ORDER BY field( id, 1, 4, 3 ) DESC
LIMIT 20

Not tested but you can try
SELECT id,
(
CASE
WHEN id = '3' THEN 0
WHEN id = '4' THEN 1
WHEN id = '1' THEN 2
END
) as rank
FROM prod
ORDER BY rank
LIMIT 20;

Related

Order by a columns count where another column has a static value

I have a table which stores user items, the two key columns which I would like to use in this query are user_id and item_id. The id field in the example is not needed but just added to show these aren't the only two columns in the table.
----------------------
id user_id item_id
----------------------
1 1 324
2 1 324
3 3 324
4 2 230
5 4 324
The query which I would like to construct should return the top 10 users who have the most items with a specific item id.
So for example if I wanted to run the query against the item ID 324 I should get the following result.
-------------------
user_id item_count
-------------------
1 2
3 1
4 1
2 0
try this
select user_id , count(*) as item_count from table
where item_id = 324 group by user_id order by item_count desc limit 10
limit 10 will show you the top 10 users and order by desc sort from high to low.
However, the above query will not give you the 0 count as per your question. If you really want the zero count you can try this: (assuming your table name is userlist)
SELECT distinct user_id,
(select
count(*) from `userlist`
where user_id=u.user_id and item_id=324
) as item_count FROM `userlist` u
order by item_count desc
I couldn't create the database in my local, but I think this will do the trick
SELECT user_id, COUNT(item_id) as item_count
FROM TABLE_NAME
WHERE item_id = 324
GROUP BY item_id
ORDER BY item_count;

Getting the sum of the column in mysql

I am using user Keevas' example, but asking a different question....
select Master_Code, SUM(Jan), SUM(Feb), SUM(Mar)
from dbo.foobar
WHERE Participating_City = 'foofoo'
GROUP BY Master_Code ORDER BY Master_Code ASC
something like this:
Master_Code sum(Jan) Sum(Feb) sum(Mar) Total
1 4 5 4 13
2 5 5 5 15
How do I get Total value column?
SELECT username,SUM(value) AS SumValue FROM
table GROUP BY username ORDER BY SumValue DESC

How can I select all the values of a database and choose one of them by a percent

What I want to do is to select a value of the database,
Lets say:
id ---- giftid ---- userid
1 1 481
2 1 422
3 7 123
4 9 542
5 1 122
6 1 455
For example, there are 4 users that want to have the same giftid:
1, 2, 5, 6
It means that each one will have 25% to be chosen.
How can I make the "percent selection"?
Assuming every userid can only claim a giftid once, you can use the ORDER BY RAND() in MySQL. This will firstly select all the rows from table table where the giftid is 1 and then the results are ordered randomly. The LIMIT 1 ensures that only the first record is returned
SELECT * FROM table
WHERE giftid = `1`
ORDER BY RAND()
LIMIT 1
Are you looking this?
SELECT giftid, 1.0 / COUNT(*) percentSelection
FROM tableName
GROUP BY giftid

Looping through MySQL Results

I'm not sure exactly how this is called but I'll try to describe as good as I can what I want to acheive.
So, first of all, there is a variable, called $id, which is actually $_GET['id']. Assuming the user is entering the following page by requesting: /page.php?id=6. Now what I need to do is to provide the information about the next 3 pages from database. Here is the database:
TABLE `pages`
id | page_name
______________________
1 | AAAAA
2 | BBBBB
3 | CCCCC
4 | DDDDD
5 | EEEEE
6 | FFFFF
7 | GGGGG
8 | HHHHH
9 | IIIII
So, while requesting the page with id 6, the following script returns the next 3 pages (7,8,9):
$res = mysql_query("SELECT * FROM `pages` WHERE `id`>'".intval($id)."' ORDER BY `id` DESC LIMIT 3");
while($arr = mysql_fetch_assoc($res))
{
print("Page ID: ".$arr['id']."; Page Name: ".$arr['page_name']."\n");
}
And here is the output:
Page ID: 7; Page Name: GGGGG
Page ID: 8; Page Name: HHHHH
Page ID: 9; Page Name: IIIII
And it works fine until the $id is greater then 6. When it is (/page.php?id={7/8/9}), the output doesn't show 3 pages any more, but 2 pages, 1 page and respectively no output when $id is 9.
So my question is: Is there a way to go back and start from the beginning when there are not enough results (less than 3) to display?
When accessing /page.php?id=8, the output should contain pages with id 9, 1 and 2.
When accessing /page.php?id=9, the output should contain pages with id 1, 2, 3.
When accessing /page.php?id=3, the output should contain pages with id 4, 5, 6 and so on.
(SELECT *, 0 AS custom_order FROM `pages` WHERE `id`>'".intval($id)."' ORDER BY `id` ASC LIMIT 3)
UNION ALL
(SELECT *, 1 AS custom_order FROM `pages` ORDER BY `id` ASC LIMIT 3)
ORDER BY custom_order, id ASC
LIMIT 3
This way you always get 3 pages. If not enough next pages, you will get up to 3 from the beginning.
You could modify the query to be something like:
select * from
(select *, id-$inval($id) as order_by
from pages were id > $inval($id) order by id asc limit 3
union
select *, id as order_by
from pages order by id asc limit 3 ) as pages
order by order_by asc
I would solve this way (one possible issue is that the resultset could contain at most 6 records instead of 3):
$res = mysql_query("(SELECT * FROM `pages` WHERE `id`>'".intval($id)."' ORDER BY `id` ASC LIMIT 3) UNION DISTINCT (SELECT * FROM `pages` WHERE id>0 ORDER BY id ASC LIMIT 3)");
$counter = 0;
while($arr = mysql_fetch_assoc($res) && $counter<3)
{
$counter++;
print("Page ID: ".$arr['id']."; Page Name: ".$arr['page_name']."\n");
}

Order by ID if two users have same number of credits

:-)
I have this script, which find a users position taken from the number of credits.
It all works, but i have a little problem. If two users have the same credits, both of them will be on the same position.
Can I do, so if there are more users with same credits, then the system need to order by the users ID and out from that give them a position?
This is my code so far:
$sql = "SELECT COUNT(*) + 1 AS `number`
FROM `users`
WHERE `penge` >
(SELECT `penge` FROM `users`
WHERE `facebook_id` = ".$facebook_uid.")";
$query_rang = $this->db->query($sql);
So if i have this:
ID -------- Credits
1 -------- 100
2 -------- 100
3 -------- 120
Then the rank list should be like this:
Number 1 is user with ID 3
Number 2 is user with ID 1
Number 3 is user with ID 2
ORDER BY credits DESC, id ASC. This will sort by credits and break ties with the id.
UPDATE
I understand now that you want the ranking information for the user, not just to sort the users by credits and ids. This will give you the complete list of users and their rankings:
SELECT #rank:=#rank+1 AS rank, users.id, users.facebook_id FROM users, (SELECT #rank:=0) dummy ORDER BY penge DESC, id ASC
Getting the row number is the tricky bit solved by this blog post:
http://jimmod.com/blog/2008/09/displaying-row-number-rownum-in-mysql/
$sql = "SELECT COUNT(*) + 1 AS `number` FROM `users` WHERE `penge` > (SELECT `penge` FROM `users` WHERE `facebook_id` = ".$facebook_uid.") ORDER BY COUNT(*) + 1 desc, users.ID";
$query_rang = $this->db->query($sql);
Later EDIT:
I don't understand why you still have the same results....
I made a quick test. I have created a table:
Test: ID (Integer) and No (Integer)
I have inserted some values:
id no
1 1
1 1
1 1
2 1
3 1
4 1
4 1
5 1
Now, if I run:
SELECT
id, COUNT(*) + 1 AS `number`
FROM
test
GROUP BY
id
I get:
id number
1 4
2 2
3 2
4 3
5 2
But if I add ORDER BY:
SELECT
id, COUNT(*) + 1 AS `number`
FROM
test
GROUP BY
id
ORDER BY
count(*) desc, id
then I get:
id number
1 4
4 3
2 2
3 2
5 2

Categories