How can I sort a query based on the average Rating in a field in my table, the field itself is JSON text, structured like:
[
{"Type":1,"Rating":5},
{"Type":2,"Rating":5},
{"Type":3,"Rating":5}
]
I need my query to be sorted by the average of the 3 Ratings. There will always ever be only 3 values for this.
My current query is:
SELECT `Name`, `Town`, `Vehicle`, `Review`, `Rating`, `Pics`, `PostedOn`
FROM `tbl_ShopReviews`
WHERE `Approved` = 1
ORDER BY `PostedOn` DESC
Current results:
Name Town Vehicle Review Rating Pics PostedOn
Kevin Chicopee 94 Corolla Great stuff, very glad I brought it here [{"Type":1,"Rating":5},{"Type":2,"Rating":5},{"Type":3,"Rating":5}] \N
Just for those like me, who googles and tries to find solution for laravel 5.4. You can use -> operator to extract JSON, that is equal to json_extract function or to column->"$.key" syntax.
$users->orderBy('column->key', 'desc');
Looks like it would be very useful in late 2013 (smile).
For example field_name has the value like
{"json_field_key1":"2016/11/24","json_field_key2":"value"}
Use this code for get the json field json_field_key1 based value in ORDER BY case
select table.*, SUBSTRING_INDEX(SUBSTRING_INDEX(field_name,'json_field_key1":"',-1),'"',1) as json_field_name from table ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(field_name,'json_field_key1":"',-1),'"',1) DESC
If your value is in date format just modify this code like
order by DATE(SUBSTRING_INDEX(SUBSTRING_INDEX(field_name,'json_field_key1":"',-1),'"',1)) DESC
Would this feature from MySQL 5.7 help? http://blog.ulf-wendel.de/2013/mysql-5-7-sql-functions-for-json-udf/
In my opinion the best solution is to be able to hook up update and insert events in your application for that reviews table and calculate the average in to another field.
Then those queries that need this info will be much easier to handle and will have a better performance.
The better solution is to parse the data before the insert, and have it ready for you in 3 columns or in 1 normalized column.
Saying that, if you're dealing with a non-changeable situation, and have exactly 3 ratings always, you can try this
ORDER BY (substring(json, 21, 1)+
substring(json, 43, 1)+
substring(json,65, 1))/3 desc;
Please consider that this solution is the least maintainable and flexible of them all, and very bug prone. The real solution is restructuring your data.
There isn't an easy way to do this, in fact, I'm not even sure it's possible.
That being said, your database structure really shouldn't contain JSON if it's something you need access to in this respect, instead, why not add a Type field to your database?
the Rating field could be a table with user, type and vlaue as columns where the user is the key. Then you can just use mysql AVG() on the value column where the key match and then sort to that.
hope this help
I need to pull a list of items from a MySQL database and then display them using PHP. I have this figured out. My question is how to change the order of the items. I know you can order them based on a certain field from the database, such as 'id' or similar.
What I need to do is do a calculation on 2 of the fields and then order the resulting list based on that calculation. For example, I need to show an Integer-X from the db and Integer-Y. I also need to show the result of Integer-X minus Integer-Y and I need to sort the list of responses based on that result of Integer-X minus Integer-Y.
Any help would be much appreciated. Thanks in advance.
You can put calculations in the ORDER BY clause:
ORDER BY integerXField - integerYField
Also, if you give an alias to the calculation in the SELECT list, you can sort by the alias:
SELECT
... integerXField - integerYField as theDiff
..
ORDER BY theDiff
I am faced with a problem coding my next feature. I want the user to be able to rearrange records and change the display_order value. I'm using Jquery UI's draggable and droppable to facilitate this.
I can see how a simple swap of display_order values would work. But I want to set a display order for a record and ideally have the others shuffle around so there are no repeated display_order values. Apart from not getting my head around how I would do that it seems like it would be hard to code and inefficient, shuffling every value around in the list.
So I am open to other suggestions of how this sort of thing is normally, or should be done.
I though of maybe using a value like 3.000 to represent the order and then when I want to make a record take its place make its value 3 - 0.001 so its 2.999 and will sort between 2 and 3. But I can see so many things wrong with that idea and doesn't seem like a good path to follow.
Thanks for any input!
add a sorting column to your table, smallint,
mediumint or int depending on the
expected number of total entries
A new entry is appended to the end, max(sorting) + 1
when reordering an item, get the new position it will be in and alter the higher sorting entries accordingly:
mysql_query('UPDATE yourTable set sorting = '.$yourNewposition.' where id='.$yourUniqueId .' LIMIT 1');
mysql_query('UPDATE yourTable set sorting = sorting + 1 where sorting >= '.$yourNewposition.' AND id != '.$yourUniqueId );
I have prices in a database as INT if I order by I get
97,650
ends of appearing before
975,455
after sorting in DESC
It appears that since the 6 in the first price is greater than the 3rd place position in the second price, it counts that as a larger number.
Has anyone run into this problem and know how to solve it?
To test, try this slow and sad query.
select prices from (table) order by (prices+0);
If that query works, then it is likely your column is not an INT column. The (prices+0) makes certain that the data is treated as an integer.
Once you have found that this does indeed work for you, you need to alter the column to be an INT column.
You should change the field type from varchar to int.
I am stuck with the following query, which won't order by it's date. Any help, or insight into what I am doing wrong will be much appreciated. The query is supposed to get an entry by thread_id, and then show the newest post in the thread, much like with a forum post, which it does fine. But when I try to order the results from newest to oldest using ORDER BY clause, it seems to ignore it.
$query = "SELECT *
FROM messages
WHERE (thread_id, received)
IN (SELECT thread_id, MAX(received)
FROM messages
WHERE receiver='$user' OR sender='$user'
AND is_hidden_receiver!='1'
GROUP BY thread_id)
ORDER BY received DESC";
Cheers, Lea
You were using the PHP time() function to generate a value to be inserted into an INT(11) column. I'm a little mystified as to why this was sorting incorrectly. I will update this answer if I figure out how to explain it concisely.
This feature is built into MySQL, it is the TIMESTAMP column type. You should probably read up on it a bit more before being happy with this solution. It has some interesting properties, depending on how to define your table, a column of type TIMESTAMP can act either as a creation timestamp or a modification timestamp.
Is the problem that it really isn't sorting by "received", or are you just getting different results than you expect? It could be order of operations on the where clause--I'm not sure if AND or OR takes precedence. Maybe try changing this:
receiver='$user' OR sender='$user' AND is_hidden_receiver!='1'
to whichever one of these you are wanting:
(receiver='$user' OR sender='$user') AND is_hidden_receiver!='1'
receiver='$user' OR (sender='$user' AND is_hidden_receiver!='1')