Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kueri Basis Data Kompleks di yii2 dengan Rekaman Aktif

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'],
    ],
]);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara menghitung perbedaan antara dua tanggal dalam bulan di MySQL

  2. Pengecualian di utas utama org.hibernate.MappingException:Entitas tidak dikenal

  3. Bagaimana cara membuat pengguna dengan hak istimewa yang sama dengan root di MySQL/MariaDB?

  4. Bagaimana cara menyimpan tanggal masa depan (!) dalam database

  5. Tampilan Daftar admin Django + ForeignKey =Daftar Ubah Kosong