MySQL ordering is lying to me - mysql

Right, this is a very odd issue that I'm wondering how i am going to explain it succinctly.
I have a WP plugin that records rows in a mysql table like so:
meta_id post_id meta_key meta_value
65387 605 _likes 9
Then on one of my pages I was running a query to select the most liked posts, ie. ORDER by meta_value DESC. Now i noticed on my site that whenever a post reached 10 it would not appear as top anymore and disappear from the query results. Odd.
I went to the database and (in PHPMyAdmin) ordered by meta_value and it did return 9 as the top results, none of the 10's appeared!?
One thing I thought it might be is the type of field (meta_value), these are the settings:
# Column Type Collation Attributes Null Default
4 meta_value longtext latin1_swedish_ci Yes NULL
Can anyone think of anything that might mean the ORDER BY is not working when the value is 10 or above!?
Thanks

If you can't change column datatype don't worry ... No need to do that
you need to just cast it's values in integers in ORDER BY clause.
user trick :
ORDER BY meta_value+0;
OR
ORDER BY CAST(meta_value as SIGNED);

Text fields don't order like number fields do. 9 is a higher value than 10 when descending (In text terms) as 10 starts with 1, and it's the 1 that it's working off, not the whole number, so 9 appears before 10.

Related

MS Access order table by order in which records were entered

I have a table in Access that I use as a progress tracker/to do list, with one field containing the date (short text) and what I did that day (long text). An example would be like this
date | progress
----------------
6/20 | did item1
| tomorrow do item2 and item3
6/21 | long text I continue in the next line for visibilty
| continued
| to do tomorrow
6/22 | item6 completed
etc. I enter these things manually. the past 3 weeks or so that I have been updating this table, it opens in the same order every time -- the order in which I created the records. Recently, the table opened in a completely random order, and continues to open in that new order.
I know now that it would have been good to create an autonumber field and order it by that, or have the date field's default value =Now(). I ahve far to many fields to make a new ID field and manually number each record in the order I created them.
Is it at all possible to force the table to order the records in either the order I created the records, or at least the previous configuration (which was just ordered by the time created)?
Also, is there a better way to be doing this...? I want to just have a record for other people who will work with this in the future. In addition, I am new to SQL, and the Access SQl has weird/unique ways of doing things, so for some queries I know I may need in the future I keep a table with the query name and some documentation for what exactly it does and some notes about the syntax (the SQL editor does not allow for -- comments). Is there a better way to do this, too?
Thanks for any help!
one field containing the date (short text)
Dates should never be stored as anything else than date values. No exceptions.
So change the data type of the field to Date, sort on this, and your troubles are gone.
To order Null dates last:
Order By Abs([DateField] Is Null), [DateField]

SELECT unique values and the associated timestamp without having the timestamp making things unique

I apologize for the poorly worded question. It's best illustrated through an example and what I've come up with so far:
Table "myInfo" has columns:
1. id (PK)
2. key
3. value
4. metaId
Table "meta" has columns:
1. id (PK)
2. metaName
3. metaValue
4. instanceNum
metaId in the "myInfo" table correlates to a instanceNum in the "meta" table. The value of the "value" column changes sometimes over different rows with the metaId. Think of the metaId as a link to a timestamp value in the "meta" table("timestamp" and its value would go into the metaName and metaValue columns respectively).
I want to select the distinct values of the 'value' column in "myInfo". So far I have:
SELECT DISTINCT mi.key, mi.value
FROM myInfo as mi JOIN metadata as meta
WHERE mi.metaId=meta.instanceNum
AND meta.key = 'timestamp'
AND mi.key='maxWeight';
But I ALSO want the timestamps associated with those values. So I want the output to look something like:
key value timestamp
maxWeight 10 tons 15:00:05 2011-01-01
maxWeight 5 tons 08:00:07 2011-10-12
maxWeight 25 tons 13:05:09 2013-08-01
I can't place timestamp as one of the columns in my SELECT because then it will return duplicate mi.attrValue values too since the timestamp makes every row unique. I tried putting the DISTINCT keyword behind only mi.attrValue but I got a MySQL error.
This is completely untested but grouping by a concat might work.
SELECT mi.key, mi.value, meta.value
FROM myInfo as mi JOIN metadata as meta ON mi.metaId = meta.id
WHERE mi.key = 'maxWeight'
AND meta.key = 'timestamp'
GROUP BY CONCAT(mi.key, mi.value)
Although you'll still have the problem of which timestamp is shown. For example, if you have 3 records for a given key/value pair, which record will be shown in your result set?
key value timestamp
maxWeight 10 tons 15:00:05 2011-01-01
maxWeight 10 tons 08:00:07 2011-10-12
maxWeight 10 tons 13:05:09 2013-08-01
The group by query will show just one of these results - but which? You'll need to think about ordering a group (which is a whole new ballgame)
SELECT mi.key, mi.value, min(meta.value)
FROM myInfo as mi JOIN metadata as meta
WHERE mi.metaId=meta.instanceNum
AND meta.key = 'timestamp'
AND mi.key='maxWeight'
group by mi.key,mi.value
Would get you what you want with the earliest timestamp value.

Is there a possibility to change the order of a string with numeric value

I have some strings in my database. Some of them have numeric values (but in string format of course). I am displaying those values ordered ascending.
So we know, for string values, 10 is greater than 2 for example, which is normal. I am asking if there is any solution to display 10 after 2, without changing the code or the database structure, only the data.
If for example I have to display values from 1 to 10, I will have:
1
10
2
3
4
5
6
7
8
9
What I would like to have is
1
2
3
4
5
6
7
8
9
10
Is there a possibility to ad an "invisible character or string which will be interpreted as greater than 9". If i put a10 instead of 10, the a10 will be at the end but is there any invisible or less visible character for that.
So, I repeat, I am not looking for a programming or database structure solution, but for a simple workaround.
You could try to cast the value as an number to then order by it:
select col
from yourtable
order by cast(col AS UNSIGNED)
See SQL Fiddle with demo
You could try appending the correct number of zeroes to the front of the data:
01
02
03
..
10
11
..
99
Since you have a mixture of numbers and letters in this column - even if not in a single row - what you're really trying to do is a Natural Sort. This is not something MySQL can do natively. There are some work arounds, however. The best I've come across are:
Sort by length then value.
SELECT
mixedColumn
FROM
tableName
ORDER BY
LENGTH(mixedColumn), mixedColumn;
For more examples see: http://www.copterlabs.com/blog/natural-sorting-in-mysql/
Use a secondary column to use as a sort key that would contain some sort of normalized data (i.e. only numbers or only letters).
CREATE TABLE tableName (mixedColumn varchar, sortColumn int);
INSERT INTO tableName VALUES ('1',1), ('2',2), ('10',3),
('a',4),('a1',5),('a2',6),('b1',7);
SELECT
mixedColumn
FROM
tableName
ORDER BY
sortColumn;
This could get difficult to maintain unless you can figure out a good way to handle the ordering.
Of course if you were able to go outside of the database you'd be able to use natural sort functions from various programming languages.

sorting numbers stored in text field in MYSQL database

i have a mySQL database with a text field in which is stored a number.
i need to produce a recordset sorted in descending numerical order.
this works fine until we get to numbers greater than 10 ie
9
8
7
6
5
4
3
2
10
1
is there a simple way of sorting this 'correctly' ?
(yes, i know i should have numbers in a numerical field, but i'm working with what i have :))
i'm using the results on an asp/vbscript/jquery page so maybe even a client-side solution is viable...
any suggestions?
ORDER BY ABS(text_column) DESC
Or, if you also have to deal with negative values:
ORDER BY CAST(text_column AS SIGNED) DESC
You need to type cast it to INTEGER using CAST function in MySQL:
ORDER BY CAST(text_column AS UNSIGNED INTEGER)
Try this one -
... ORDER BY text_column * 1

Filtering SQL results

I would like to show a filtered result to a few ip's that keep scraping my content. I have blocked them with .htaccess and they change their ip address and continue doing it. So I thought, I want to create a soft block that won't show them all of my content and hopefully they won't even notice.
My table has a auto_increment field
id | category | everything else
1 1
2 1
3 4
4 2
I have been trying something like this.
SELECT * from mytable WHERE `category` = '1' having avg(id/3) = 1 ORDER BY `id` DESC LIMIT 0 , 10
I have searched forever but I am a newb to sql, so I don't even really know what I am searching for. I hope somebody here can please help me! Thanks :)
If you want to get remainder of division by 3, you should use % operator.
SELECT * from mytable WHERE `category` = '1' and id % 3 = 1 ORDER BY `id`
DESC LIMIT 0 , 10
Generally, the ID column is not for doing computations on it. It does not represent anything other than unique identifier of the record (at most, it should be used to sort the records chronologically) - you could have there GUIDs for example, and your application should work.
If you want to store the IPs that you want to block in your DB, consider adding another column to your table, call it status or something similar, and store in this column the status for that ip - this status could be clean, suspicious, blocked, etc. After that, your SELECT should look only after the rows with blocked status