Forum Moderators: coopster

Message Too Old, No Replies

Ordering fields twice in MySQL

is this possible?

         

dreamcatcher

11:21 pm on Apr 10, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Is it possible to order something twice from a mysql command? For instance I`m pulling the last 10 entries from a database by id number, using DESC. Is it then possible to order these entries in alphabetical order?

SELECT FROM table WHERE row = 'blah' ORDER BY id DESC AND ORDER BY name

?

Thanks.

lorax

12:41 am on Apr 11, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Yes you may..

ORDER BY id DESC, name ASC

ORDER BY [dev.mysql.com]

dreamcatcher

6:36 am on Apr 11, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



mmm...thats not working I`m afraid. I checked the mysql website from the link you gave me and your syntax is correct, so I can`t see why its not working. It still displays in reverse.

This is my query:


$query = "SELECT * FROM covers ORDER BY id DESC, scanname ASC LIMIT 10";
$result = mysql_query($query) or die(mysql_error());

Would the limit clause affect anything?

ergophobe

3:59 pm on Apr 11, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The limit clause is applied after the sort, so it should give you the first ten records based on your sort.

dreamcatcher

6:22 pm on Apr 11, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks ergophobe. I didn`t think the LIMIT clause was the problem, only I`ve been clutching at straws trying to figure out why the second part of the ORDER BY isn`t working. Could it be server related?

timster

1:42 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ORDER BY id DESC, name ASC

This code will sort by ID, and if there are records with identical ID's, it will sort them by name. I don't think that's what you want. You're looking to get the highest 10 ID's, and then sort them by name, right?

I think what you may need is a subquery. This page may help:

[dev.mysql.com...]

The following SQL statement may work in MySQL 4.1 and newer (unfortunately I'm running 4.0 here so can't really check.)

SELECT * FROM covers
WHERE ID IN (select ID from covers order by id DESC limit 10)
ORDER BY scanname ASC

dreamcatcher

8:12 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You're looking to get the highest 10 ID's, and then sort them by name, right?

Yep, thats exactly what I`m after timster. I tried your code but it gave me a syntax error. I looked at the link you gave me and did a search on google, but I`m not really understanding the sub query thing.

coopster

8:29 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



MySQL won't allow LIMIT in a subquery clause...yet.

Will you have multiple id's for name?

ergophobe

9:45 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



How about my favorite method: brute force

- a SELECT INSERT of the first ten IDs into a temporary table and then another select ordered by name.

- or use array_multisort()

function get_name_list($col1='blah'){

$query = "SELECT id, name FROM table WHERE col1='$col1' ORDER BY id DESC LIMIT 10";
$result = mysql_query($query);

$i=0;

while ($row = mysql_fetch_assoc($result) ) {
$row_array[$i] = $row;
$name_array[$i] = $row['name']
$i++
}

array_multisort($name_array, $row_array);

return $row_array;
}

Or something along those lines

dreamcatcher

11:19 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



LOL! I like the brute force approach. Thanks for the code ergophobe, I`ll give that a try. I had thought about doing it that way, but I figured if there was a simple SQL command, that would be easier. Thanks again.

ergophobe

11:29 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The thing with temporary tables is pretty easy, but I don't know how much overhead there is. Since it's such a small result set, I bet that PHP can just run through it faster as in second brute force method. It's a little extra php (you have to loop through the result set anyway, so no extra fetches) to make the SQL simpler.

With the first method you need to create a temp table, select into it, get everything out of it, and then delete the table.

coopster

11:38 pm on Apr 12, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Do you have multiple (or identical) id's for name as timster questioned...?

If not, you may be able to get by with...

SELECT 
DISTINCT id,
scanname,
the_rest_of_your_columns
FROM covers
ORDER BY id DESC, scanname ASC LIMIT 10
;

One other note, if

scanname
is of type
ENUM
,
SET
, etc. your
ORDER BY
won't work as you are expecting...

ergophobe

12:50 am on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



coopster,

Won't that still give you a result set sorted first by id and then by name?

If there are no multiple ids (i.e. id is unique), won't select id and select distinct yield the same result set?

coopster

1:08 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Right. I meant to say "If so, you may be able to get by with..." rather than "If not, ..."

Sorry for the confusion. I did test it, though ;)

All-in-all, it depends on the dataset being used and the table structure. I am still uncertain as to the structure...

ergophobe

3:34 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



heh heh... I was thinking: "That seems so simple, but I don't understand at all how that could work."

timster

3:41 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ergophobe's "brute force" should work fine. (Heck, it's only 10 records, how much force is it going to take?)

If you're interested in having MySQL do all the heavy lifting instead of PHP, something like this might be good. (For a change, these queries do work in MySQL 4.0.)

1. select id from tabe_name order by id DESC limit 10;

2. fetch the rows and feed the ID's into a string delimited by commas

3. select * from tabe_name where id in ($string) order by name

ergophobe

3:50 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Timster, that's a pretty good one.

Yeah, the small record set is why I thought he might want to just do it with PHP. As you point out, the 'brute force' method isn't all that brute. It adds only four lines of php and saves at least one query. And the lines it adds, namely:


$i=0;
$name_array[$i] = $row['name']
$i++

array_multisort($name_array, $row_array);

are just two assignments, an increment and a built-in function call. I would think it would benchmark at least as fast as any mysql-oriented solution.

If you want mysql to do it all, though, the temp table method should work pretty well, perhaps as fast as what Timster suggested. By default the table will only be created in memory, so it should be quite fast.

dreamcatcher

5:09 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Just to clear up about the table attributes. id is an auto increment field and scanname is a varchar field. timster, can you just elaborate on "fetch the rows and feed the ID's into a string delimited by commas". I only really know the basics of mysql, so thats got me confused. Thanks.

ergophobe

5:36 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



"in" allows you to specify a set to check against so

id in ('1', '2', '7')

would match if id=7, but not if id=6

so
$ids = "";
while ($row = mysql_fetch_array($q)) {
$ids .= "'" . $row['id'] . "',";
}

substr($ids, 0, -1); // to strip off the last comma

timster

5:38 pm on Apr 13, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



timster, can you just elaborate on "fetch the rows and feed the ID's into a string delimited by commas"

That work would be done in PHP. Sorry I don't have time to write real code, but it would look a little like this:

# Caution Pseudo Code -- syntax probably complete junk

$query1 = "select id from table order by id desc limit 10";
$result = mysql_query($query1);
$string = '';
while ($row = $fetchrow_arrayref($result)) { $string .= $row . "," }
$string = preg_replace("/\,$/","",$string);
$query2 = "select * from table where id in ($string);

Be aware there are probably better ways to write this PHP, as I'm still on the PHP learning curve, to say the least.

dreamcatcher

3:36 pm on Apr 15, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks guys. Well, at least I have something to play around with.