saya akan berasumsi, berdasarkan pertanyaan yang Anda ajukan di sini Anda menyukai komentar bahwa Anda memberikan seluruh kueri (tidak ada bidang lain, yang Anda keluarkan hanya untuk menunjukkan kode sampel)
oleh karena itu, jika Anda hanya membutuhkan bidang yang ditentukan dalam SELECT
pernyataan, Anda dapat sedikit mengoptimalkan kueri Anda:
pertama, Anda bergabung dengan host_machines
hanya untuk menautkan cameras
dan events
, tetapi memiliki kunci yang sama host_machines_idhost_machines
di keduanya, jadi tidak perlu, Anda bisa langsung:
INNER JOIN events events
ON (events.host_machines_idhost_machines =
cameras.host_machines_idhost_machines))
kedua, gabungkan dengan ispy.staff
, satu-satunya bidang yang digunakan adalah idreceptionist
di WHERE
klausa, bidang itu ada di events
juga agar kami dapat menghapusnya sepenuhnya
pertanyaan terakhir di sini:
SELECT videos.idvideo, videos.filelocation, events.event_type, events.event_timestamp
FROM videos videos
INNER JOIN cameras cameras
ON videos.cameras_idcameras = cameras.idcameras
INNER JOIN events events
ON events.host_machines_idhost_machines =
cameras.host_machines_idhost_machines
WHERE (events.staff_idreceptionist = 182)
AND (events.event_type IN (23, 24))
AND (events.event_timestamp BETWEEN videos.start_time
AND videos.end_time)
harus menampilkan catatan yang sama dengan yang ada di pertanyaan Anda, tanpa baris yang sama
beberapa duplikat video akan tetap ada karena hubungan satu ke banyak antara cameras
dan events
sekarang ke sisi yii,
Anda harus mendefinisikan beberapa hubungan di Video model
// this is pretty straight forward, `videos`.`cameras_idcameras` links to a
// single camera (one-to-one)
public function getCamera(){
return $this->hasOne(Camera::className(), ['idcameras' => 'cameras_idcameras']);
}
// link the events table using `cameras` as a pivot table (one-to-many)
public function getEvents(){
return $this->hasMany(Event::className(), [
// host machine of event => host machine of camera (from via call)
'host_machines_idhost_machines' => 'host_machines_idhost_machines'
])->via('camera');
}
Pengontrol Video dan fungsi pencarian itu sendiri
public function actionIndex() {
// this will be the query used to create the ActiveDataProvider
$query =Video::find()
->joinWith(['camera', 'events'], true, 'INNER JOIN')
->where(['event_type' => [23, 24], 'staff_idreceptionist' => 182])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time');
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
}
yii akan memperlakukan setiap video sebagai satu record (berdasarkan pk), artinya semua duplikat video akan dihapus. Anda akan memiliki satu video, masing-masing dengan beberapa acara sehingga Anda tidak akan dapat menggunakan 'event_type'
dan 'event_timestamp'
dalam tampilan tetapi Anda dapat mendeklarasikan beberapa getter di dalam Video model untuk menunjukkan info itu:
public function getEventTypes(){
return implode(', ', ArrayHelper::getColumn($this->events, 'event_type'));
}
public function getEventTimestamps(){
return implode(', ', ArrayHelper::getColumn($this->events, 'event_timestamp'));
}
dan tampilan menggunakan:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'idvideo',
'eventTypes',
'eventTimestamps',
'filelocation',
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
edit :
jika Anda ingin menyimpan video duplikat, nyatakan dua kolom dari events
di dalam Video model
public $event_type, $event_timestamp;
pertahankan GridView
yang asli setup, dan tambahkan select
dan indexBy
ini ke kueri di dalam VideoController :
$q = Video::find()
// spcify fields
->addSelect(['videos.idvideo', 'videos.filelocation', 'events.event_type', 'events.event_timestamp'])
->joinWith(['camera', 'events'], true, 'INNER JOIN')
->where(['event_type' => [23, 24], 'staff_idreceptionist' => 182])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time')
// force yii to treat each row as distinct
->indexBy(function () {
static $count;
return ($count++);
});
perbarui
staff
langsung kaitannya dengan Video
saat ini agak bermasalah karena jaraknya lebih dari satu tabel. ada masalah tentangnya di sini
namun, Anda menambahkan staff
tabel dengan menautkannya ke Acara model,
public function getStaff() {
return $this->hasOne(Staff::className(), ['idreceptionist' => 'staff_idreceptionist']);
}
yang akan memungkinkan Anda untuk menanyakan seperti ini:
->joinWith(['camera', 'events', 'events.staff'], true, 'INNER JOIN')
Pemfilteran akan memerlukan beberapa pembaruan kecil pada pengontrol, tampilan, dan SarchModel
inilah implementasi minimalnya:
class VideoSearch extends Video
{
public $eventType;
public $eventTimestamp;
public $username;
public function rules() {
return array_merge(parent::rules(), [
[['eventType', 'eventTimestamp', 'username'], 'safe']
]);
}
public function search($params) {
// add/adjust only conditions that ALWAYS apply here:
$q = parent::find()
->joinWith(['camera', 'events', 'events.staff'], true, 'INNER JOIN')
->where([
'event_type' => [23, 24],
// 'staff_idreceptionist' => 182
// im guessing this would be the username we want to filter by
])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time');
$dataProvider = new ActiveDataProvider(['query' => $q]);
if (!$this->validate())
return $dataProvider;
$this->load($params);
$q->andFilterWhere([
'idvideo' => $this->idvideo,
'events.event_type' => $this->eventType,
'events.event_timestamp' => $this->eventTimestamp,
'staff.username' => $this->username,
]);
return $dataProvider;
}
}
pengontrol:
public function actionIndex() {
$searchModel = new VideoSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('test', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
dan pemandangan
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'idvideo',
'filelocation',
[
'attribute' => 'eventType', // from VideoSearch::$eventType (this is the one you filter by)
'value' => 'eventTypes' // from Video::getEventTypes() that i suggested yesterday
// in hindsight, this could have been named better, like Video::formatEventTypes or smth
],
[
'attribute' => 'eventTimestamp',
'value' => 'eventTimestamps'
],
[
'attribute' => 'username',
'value' => function($video){
return implode(', ', ArrayHelper::map($video->events, 'idevent', 'staff.username'));
}
],
//['class' => 'yii\grid\ActionColumn'],
],
]);