I've been looking like crazy but I can't seem to find a way of achieving something similar to this with Laravel's Eloquent:
select id,name
from friends
order by id=5 desc
Example taken from the following link: mysql SQL: specific item to be first and then to sort the rest of the items
I was hoping a simple Group::orderBy('id', $id, 'DESC')->get() would work, but no such luck.
I've also looked into using DB instead but the orderBy method for that class takes in exactly the same arguments and doesn't have an option for specific IDs. Are there any alternatives?
Thank you very much for all the help!
not sure , but may be you could try using orderByRaw(), like,
$id = 5;
Group::orderByRaw(DB::raw("FIELD(id, $id)"))
->get();
Related
I'm trying to figure out what's the best way of getting the index of the given Model in the Collection.
Scenario : list of videos, which belong to a specific title. Title can have one or more videos. When on the given video page with the Video model at hand, I would like to display something along the lines Video ? of ?.
Basically what I need to achieve is something that would reflect the following, raw sql statement:
SELECT `v`.*
(
SELECT COUNT(`id`)
FROM `videos`
WHERE `title_id` = ?
AND `identity` <= `v`.`identity`
) AS `collection_index`
FROM `videos` `v`
WHERE `v`.`id` = ?
Where identity is simply some field that is used to sort videos - might be numerical but also string in the format 01-03 etc. In the above collection_index would store the index (or rather sequential position) of the given record in the collection.
Is it possible with a single statement on the Eloquent model - anyone came across a similar problem?
UPDATE / SOLUTION
After some digging and help from #JarekTkaczyk, I've managed to come up with a solution - for those who also might face the same problem.
Here's my model using sub-query to achieve the above.
return Video::select('videos.*')
->selectSub("
SELECT COUNT(v.id)
FROM videos as v
WHERE v.title_id = videos.title_id
AND v.identity <= videos.identity
",
'collection_index'
)
->selectSub("
SELECT COUNT(v.id)
FROM videos as v
WHERE v.title_id = videos.title_id
",
'collection_count'
)
->find(id);
Hope it will help someone.
I do not think this is a Laravel specific question. You have a result set, ordering of which is defined by your specific conditions. When you are on the detail page, your result set is lost. You have only detailed record.
So, you might want to cache position of each video in the list, for example.
I'm using Laravel 4 and I'm running into an issue with eloquent.
I've got it set up to grab the category, get the products and limit it to 2. However I'm having trouble getting the random element. I need it to select from two random products, rather than the newest/latest.
$products = Category::find($id)->products->take($limit);
$products->load('imageThumb');
return $products;
I'd like to keep the solution eloquent based, but if that's not an option I'll switch to a raw query code.
Thanks!
$products = Category::find($id)->products()->orderBy(DB::raw('RAND()'))->take($limit)->get();
(sorry forgot the ->get() in my original answer)
How's big is the table? If it is not too big you can use MySQL ORDER BY RAND()
http://davidwalsh.name/mysql-random
Eloquent something like:
->orderBy(DB::raw('RAND()'))
I have a doubt on how I should write my query on CakePHP.
Instead of using the querybuilder from CakePHP I´d like to use the statement query.
So I my query is:
SELECT `Post`.id, `Post`.title, COUNT(`Like`.id) AS `Posts_Liked`
FROM posts AS `Post`, likes AS `Like`
WHERE `Post`.id = `Like`.posts_id;
But when I send the result to the View page, I can´t get the count number when calling $post['post']['Posts_Liked'], so how should I call this data in the view?
Aggregation result will not be added to the data array as per the doc
You should either use virtual fields or get the data like this :
$post[0]['Posts_Liked']
you can inspect your data using
debug($post);
to see how your array is structured.
Using virtual fields you could achieve this like this:
$this->Post->virtualfields['Posts_liked'] = 0;
$this->Post->query('SELECT `Post`.id, `Post`.title, COUNT(`Like`.id) AS `Posts_liked` FROM posts AS `Post`, likes AS `Like` WHERE `Post`.id = `Like`.posts_id;');
and then get your data as per usual
$post['Post']['Posts_liked']
If you want it permanent, you should give a try to the counterCache
Try doing a pr($post); die(); right after making your model call, before it even gets to the view. I'm thinking it may be referenced by $post[0]['Posts_Liked'], since it's an aggregate function. You'll notice that CakePHP puts SUM(), MAX(), COUNT(), etc. in a $result[0]['count']; kind of notation. Hope this helps.
CakePHP's pr() function is much better than print_r, imho.
I have this code so far which is within 2 while loops:
mysql_query("SELECT * FROM listing WHERE
(category_id='$category' OR category_id_2='$category' OR category_id_3='$category')
AND listing_status='1' AND listing_type='1' AND listing_id='$listing_id'
ORDER BY overall DESC");
The data is showing exactly what I want, however the ORDER BY simply isn't working. I'm not too sure what it's ordering by. The overall column itself is DECIMAL(12,2).
The values are saved to only 2 decimal places. For instance, in each row it could be 2.56, 2.89. In this case I want the 2.89 to show before the 2.56. However, it's not.
Many thanks in advance.
I believe you are only selecting one element at a time in your query, something like
while(...){
$category = ...;
$listing_id = ...;
// Your query which only returns one result here
}
Then since your query only returns one result it has nothing to sort, and you see the results in the order the queries are executed.
You need to rewrite your query to select all the rows you want in one go instead of having it in a loop if you want ORDER BY to work. Using IN in your query may help you.
Have you tried casting the field as a decimal in the order by?
ORDER BY CAST(overall as DECIMAL) DESC
I have managed to solve the problem.
By implementing the 'overall' column in the first loops table, instead of the second. It orders the data first by overall, and then goes ahead and gathers the other data from the second table.
Many thanks for your help.
Try:
mysql_query("SELECT * FROM listing WHERE
(category_id='$category' OR category_id_2='$category' OR category_id_3='$category')
AND listing_status='1' AND listing_type='1' AND listing_id='$listing_id'
ORDER BY overall+0 DESC");
The query is fine. The problem is probably with how you iterate returned data. Try changing it.
If not, provide us with the whole relevant piece of your PHP code.
I don't know why, but I found out by copying and pasting from phpmyadmin that this worked to solve a similar problem. The ' is changed to ` - dunno if it's important. But definitely ASC worked with the second way.
Important - the have been stripped from the second method, put them around the table name and the column names.
instead of
$sql = "SELECT * FROM 'dczcats' ORDER BY 'first' , 'second' ASC";
I typed this
$sql = "SELECT * FROM `dczcats` ORDER BY `dczcats`.`first` , `dczcats`.`second` ASC";
I'm trying to sort a collection by attribute_id. I thought it would be easy, but I think I'm not using it correctly:
$attributes = Mage::getResourceModel('eav/entity_attribute_collection')
->setOrder('attribute_id');
echo $attributes->getSelect();
Result:
SELECT `main_table`.* FROM `eav_attribute` AS `main_table`
Why isn't there any order by?
You're actually doing it the right way. However, since Magento uses EAV, it needs to apply tricks to help performance.
One of these tricks is the timing used to build the eventual SQL string. Usually it's lazily loaded at the last minute and it's not until you actually indicate you want to access a collection's data, that you can see the full SQL used to produce the collection. For example running your code, but prompting magento to actually construct and load the collection, produces the expected output.
$attributes = Mage::getResourceModel('eav/entity_attribute_collection')
->setOrder('attribute_id');
$attributes->count(); // forces the collection to load
echo $attributes->getSelect()->assemble();
This results in the SQL:
SELECT `main_table`.* FROM `eav_attribute` AS `main_table` ORDER BY attribute_id DESC
So you were on the right path, just Magento was doing its level best to confuse you. It's very good at that.
Use this instead of $attributes->getSelect();:
$attributes->getSelect()->order('main_table.attribute_id ASC');
Don't ask why.