简体   繁体   中英

How to choise a line that is created more than 20 minutes and less than 30 with the help of Eloquent and without raw sql?

I have the following SQL query (postgres is my database):

select distinct *
from "customers"
         inner join "customer_events" on "customer_events"."customer_id" = "customers"."id"
         inner join "customer_event_types" on "customer_events"."customer_event_type_id" = "customer_event_types"."id"
where "customer_event_types"."code" =  'Reg'
and (current_timestamp - customer_events.created_at) > (20 *  60 * '1 sec'::interval)
and (current_timestamp - customer_events.created_at) < (30 *  60 * '1 sec'::interval)

I think it is not very difficult to understand my business-logic from this query: I have customers, customers make events, each event has event type. It's pretty simple, but the main problem is to take clients that have particular events that exist more than 20 minutes and less than 30. This request works for my (I believe I have't mistakes with date).

How to write the same with the help of Eloquent, but without raw SQL. Is it possible without raw SQL?

I have this code, but it contains raw SQL:

$tmp = DB::table('customers')->select('customers.idfa', 'customers.idfv', 'customers.app_build_number', 'customers.os_version', 'customers.model')->distinct()
    ->join('customer_events', 'customer_events.customer_id', '=', 'customers.id')
    ->join('customer_event_types', 'customer_events.customer_event_type_id', 'customer_event_types.id')
    // event is my object, that contains event_code and time intervals
    ->when($events, function ($query, $events) {
        foreach ($events as $event) {
            if (!isset($event->event_code) || empty($event->event_code)) {
                continue;
            }

            $query->where('customer_event_types.code', '=', $event->event_code);

            if (isset($event->minutes_from) && !empty($event->minutes_from)) {
                $query->whereRaw("(current_timestamp - customer_events.created_at) > ($event->minutes_from *  60 * '1 sec'::interval)");
            }
            if (isset($event->minutes_to) && !empty($event->minutes_to)) {
                $query->whereRaw("(current_timestamp - customer_events.created_at) < ($event->minutes_to *  60 * '1 sec'::interval)");
            }

        }
        return $query;
    });

You can create a timestamp range for the time period -30min and -20min and use the range element is contained operator (<@). In raw sql that would be

where event_date <@ tsrange ( localtimestamp - interval '30 min', localtimestamp - interval '20 min', '()')  

I'm not familiar with the necessary Eloquent syntax, but extrapolating from your post it appears that the following might be doable

$query->whereRaw("$event <@ tsrange (localtimestamp - interval '30 min', localtimestamp - interval '20 min', '()')");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM