从远程相关表中获取N行,条件与密切相关的表有关

时间:2014-10-28 22:46:42

标签: mysql laravel laravel-4 eloquent

我有两个表,schedulesshifts,关系是一对多。

schedule包含daymonthyear字段以及is_published布尔值。 shift user_idusers具有一对一的关系。

现在,我想获得shifts的下一个即将到来的user。我必须从schedule开始,因为该表中包含日期。但是,更重要的是,我应该只检索属于已发布的shifts的{​​{1}}。

所以最大的问题是:

参赛作品数量应为5班制。但是,从计划开始,我不知道需要检索多少计划,直到有5个属于用户的班次。

除了试验和错误(即检索x下一个时间表并进行测试以查看是否存在足够的班次。如果没有,检索下一个n个时间表直到满足配额),是否有替代方案?

附表架构

schedule

此处,Schema::create('schedules', function(Blueprint $table) { $table->increments('id'); $table->integer('user_id', false, true); $table->integer('client_id', false, true); $table->datetime('for'); $table->enum('type', array('template', 'revision', 'common')); $table->string('name', 50)->default('Untitled Template'); $table->boolean('is_published'); $table->timestamp('published_at'); $table->softDeletes(); $table->timestamps(); }); 是创建者的ID,而不是时间表所属的身份。这用于跟踪未来如何创建计划。

转变架构

user_id

3 个答案:

答案 0 :(得分:0)

SELECT user.name,inner_q。* FROM user, (SELECT sch.year,sch.month,sch.day,sh.start_time FROM schedule sch INNER JOIN shift sh ON sch.id = sh.schedule_id WHERE sch.is_published = TRUE AND sh.user_id = user.id LIMIT 5)AS inner_q;

答案 1 :(得分:0)

好的,我不知道我是否做得好,但试一试:

User::find($userId)
    ->shifts()
    ->with('schedule')
    ->where('is_published', true)
    ->orderBy('year', 'asc')
    ->orderBy('month', 'asc')
    ->orderBy('day', 'asc')
    ->take(5)
    ->get();

<强>更新

第二次尝试,希望这有效

User::find($userId)
    ->schedules()
    ->has('shifts')
    ->where('is_published', true)
    ->orderBy('year', 'asc')
    ->orderBy('month', 'asc')
    ->orderBy('day', 'asc')
    ->take(5)
    ->get();

另一次更新

第三次是魅力:)

$results = User::find($userId)
    ->schedules()
    ->where('is_published', true)
    ->orderBy('year', 'asc')
    ->orderBy('month', 'asc')
    ->orderBy('day', 'asc')
    ->take(5)
    ->get();

为此,您需要在用户模型中使用此功能:

public function schedules(){
    return $this->belongsToMany('Schedule', 'shifts');
}

然后,要访问班次,您可以使用pivot属性:

foreach($results as $result){
    echo $result->pivot
}

如果您想要完整的Shift模型而不仅仅是属性,请将其定义为Pivot Model:

class Shift extends Illuminate\Database\Eloquent\Relations\Pivot

并在Schedule模型中:

public function newPivot(Eloquent $parent, array $attributes, $table, $exists){
    if ($parent instanceof User) {
        return new Shift($parent, $attributes, $table, $exists);
    }
    return parent::newPivot($parent, $attributes, $table, $exists);
}

答案 2 :(得分:0)

我会采取简单的方法:

// User model
public function shifts()
{
   return $this->hasManyThrough('Shift', 'Schedule');
}

然后:

$now = Carbon\Carbon::now();

$upcomingShifts = $user->shifts()
     ->where('schedules.is_published', 1)
     ->where('schedules.for', '>', $now)
     ->orderBy('schedules.for')
     ->take(5)
     ->get();

你可以让它更灵活,例如。这样:

// User model
public function getUpcomingShifts($limit = 5)
{
   $joinTable = $this->shifts()->getParent()->getTable(); // schedules

   $now = Carbon\Carbon::now();

   return $this->shifts()
     ->where($joinTable.'.is_published', 1)
     ->where($joinTable.'.for', '>', $now)
     ->orderBy($joinTable.'.for')
     ->take($limit)
     ->get();
}

// then
$user->getUpcomingShifts();