Kohana ORM ordering - orm

I'm using Kohana's ORM library, and I'm wondering if there is any way to select DB records in a particular predetermined sequence.
$products_ids = array('5', '6', '1', '33', '2');
$products = ORM::factory('Product')->where('state', '=', 1)
->and_where('id', 'IN', $products_ids)->find_all();
This orders result by primary key (id). So result records ordered like (1, 2, 5, 6, 33). How select records by order defined in $products_ids ('5', '6', '1', '33', '2')?
Thanks.

Yes this is possible.
$products = ORM::factory('Product')->where('state', '=', 1)
->and_where('id', 'IN', $products_ids)->order_by('product_id', 'desc')->find_all();
Note the added order_by() in the string above.
You can order your results now. It has more cool features like group_by().
Read the documentation and you will find more unexpected magic in ORM.

In MySQL you can have conditions in order by clause where if the condition match it gets treated as 1 and 0 on fails.
The code for the example would be:
$products_ids = array('5', '6', '1', '33', '2');
$products = ORM::factory('Product')->where('state', '=', 1)->and_where('id', 'IN', $products_ids);
foreach($products_ids as $product_id)
{
$products->order_by(DB::expr('id='.$product_id), 'desc');
}
$products = $products->find_all();
In MySQL it would look something like this:
SELECT * FROM products WHERE ... ORDER BY id=5 DESC, id=6 DESC, id=1 DESC, id=33 DESC, id=2 DESC;

I don't know why you wan do so stupid thing, but 2 answers you have. (For stric problem. But probably you don't show full background.
I propose 2 scenarios:
Products on page category - add column for order it to table.
Display shopping chart - order by order_item_id
BTW: ORM is comfortable, but slow, so if you nedd it only for display (read operation) better is using raw query. Here solution for ORM.
public function get_ordered(array $ids){
if(empty($ids))
return array();
$res = DB::select->from($this->_table_name)
->where($this->primary_key(),'IN',$ids)
->execute($this->_db)->as_array($this->primary_key());
$out = array();
foreach($ids AS $one){
if(isset($res[$one]))
$out[$one] = $res[$one];
}
return $out;
}

Related

Laravel query with where and where

I've trying to basically do two SQL requests into one laravel array.
These are my SQL
SELECT * FROM `transactions` WHERE `plan` LIKE '1050' ORDER BY `updated_at` DESC
SELECT * FROM `transactions` WHERE `user` LIKE '1050' ORDER BY `updated_at` DESC
I want to have all transaction that have "plan" == "1050" AND all transactions that have "user" == "1050" in one variable.
This is not working for me:
$ct=transactions::where('user',$user->id)
->orWhere('plan', $user->id)
->orderby('created_at',"asc")->get();
The context agnostic way to combine the results of two union compatible queries (such as yours) would be:
$result = transactions::where('plan', 'LIKE', $user->id)->orderBy('updated_at', 'DESC')
->union(
transactions::where('user', 'LIKE', $user->id)
->orderBy('updated_at', 'DESC')
)
->get();
This of course means that the results are ordered by plan then user. You can sort them by updated_at globally using the below function on the result:
$result = $result->sortBy('updated_at', 'DESC');
There's also a way to do it on the query level but I don't see much benefit since you're getting all the data anyway.
The above query should be functionally equivalent to:
$result = transactions::orWhere('plan', 'LIKE', $user->id)
->orWhere('user', 'LIKE', $user->id)
->orderBy('updated_at', 'DESC')
->get();
This will have the same results but in a different order than the union.

Laravel Eloquent with `has` and `where` on dates

I try to get records on relation when there is only one record in the one to many relation and only the records where the start_date is bigger than now() and here is what I'm trying:
$newStarters = User::has('periods', 1)->with(['periods' => function($q) {
$q->where('start_date', '>', Carbon::now()->subWeek(2)->format('Y-m-d') );
}])->get();
in this case the date filter does not applies.
What is the propper way to do this?
Probably you are looking this:
$newStarters = User::whereHas('periods', function($q) {
$q->where('start_date', '>', Carbon::now()->subWeek(2)->format('Y-m-d') );
}, '=', 1)->get();
See Query relationship existence section for more details.

Join Statement using Query builder with multiple where clause

I have a Query builder statement below and I would want to introduce another condition to the query. However, I can not get this right.
This query works fine;
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();
I would want to introduce another where statement; this ->whereRaw('DATE(c.sent_time) != CURDATE()'). Meaning the query above should only pick values where subscription_services_msisdn.sent_time DATE(c.sent_time) IS NOT EQUAL to Current Date CURDATE().
Anyone lead me here. Regards.
You can chain as many where conditions as you want, so just add another whereRaw to the chain:
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->whereRaw('DATE(c.sent_time) <> CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();

SQL server query on json string for stats

I have this SQL Server database that holds contest participations. In the Participation table, I have various fields and a special one called ParticipationDetails. It's a varchar(MAX). This field is used to throw in all contest specific data in json format. Example rows:
Id,ParticipationDetails
1,"{'Phone evening': '6546546541', 'Store': 'StoreABC', 'Math': '2', 'Age': '01/01/1951'}"
2,"{'Phone evening': '6546546542', 'Store': 'StoreABC', 'Math': '2', 'Age': '01/01/1952'}"
3,"{'Phone evening': '6546546543', 'Store': 'StoreXYZ', 'Math': '2', 'Age': '01/01/1953'}"
4,"{'Phone evening': '6546546544', 'Store': 'StoreABC', 'Math': '3', 'Age': '01/01/1954'}"
I'm trying to get a a query runing, that will yield this result:
Store, Count
StoreABC, 3
StoreXYZ, 1
I used to run this query:
SELECT TOP (20) ParticipationDetails, COUNT(*) Count FROM Participation GROUP BY ParticipationDetails ORDER BY Count DESC
This works as long as I want unique ParticipationDetails. How can I change this to "sub-query" into my json strings. I've gotten to this query, but I'm kind of stuck here:
SELECT 'StoreABC' Store, Count(*) Count FROM Participation WHERE ParticipationDetails LIKE '%StoreABC%'
This query gets me the results I want for a specific store, but I want the store value to be "anything that was put in there".
Thanks for the help!
first of all, I suggest to avoid any json management with t-sql, since is not natively supported. If you have an application layer, let it to manage those kind of formatted data (i.e. .net framework and non MS frameworks have json serializers available).
However, you can convert your json strings using the function described in this link.
You can also write your own query which works with strings. Something like the following one:
SELECT
T.Store,
COUNT(*) AS [Count]
FROM
(
SELECT
STUFF(
STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, ''),
CHARINDEX('"Math"',
STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, '')) - 3, LEN(STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, '')), '')
AS Store
FROM
Participation
) AS T
GROUP BY
T.Store

How to compare value in two columns in FuelPHP

I have problem when query table using FuelPHP 1.3's Model.
Entries table have three columns ('id', 'status', 'current', 'max' ).
$result = Model_Entry::query()
->where('status', 1)
->where('count_current', '>=', 'count_max');
I want to use 'where' method's third argument as column name, but it handled as value in generated query.
Example
SELECT * FROM `entries` AS `t0` WHERE `t0`.`status` = 1 AND `t0`.`count_current` >= 'count_max'
My Goal
SELECT * FROM `entries` AS `t0` WHERE `t0`.`status` = 1 AND `t0`.`count_current` >= `t0`.`count_max`
Any help would be appreciated.
To achieve what you want, you have to use DB::expr()
So, your code will be:
$result = Model_Entry::query()
->where('status', 1)
->where('count_current', '>=', DB::expr('count_max'));