Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

सक्रिय रिकॉर्ड के साथ yii2 में जटिल डेटाबेस क्वेरी

मैं मान लूंगा, आपके द्वारा पूछे गए प्रश्न के आधार पर यहां आपको टिप्पणियों में पसंद आया कि आपने पूरी क्वेरी प्रदान की (कोई अन्य फ़ील्ड नहीं, जिसे आपने केवल नमूना कोड दिखाने के लिए निकाला था)

इसलिए, यदि आपको केवल SELECT . में निर्दिष्ट फ़ील्ड की आवश्यकता है कथन, आप अपनी क्वेरी को काफी हद तक अनुकूलित कर सकते हैं:

सबसे पहले, आप host_machines . के साथ जुड़ रहे हैं केवल cameras को जोड़ने के लिए और events , लेकिन एक ही कुंजी है host_machines_idhost_machines दोनों पर, ताकि इसकी आवश्यकता न हो, आप सीधे कर सकते हैं:

    INNER JOIN events events
        ON (events.host_machines_idhost_machines =
            cameras.host_machines_idhost_machines))

दूसरे, ispy.staff . के साथ जुड़ें , केवल इस्तेमाल किया जाने वाला फ़ील्ड idreceptionist . है WHERE . में खंड, वह फ़ील्ड events . में मौजूद है साथ ही ताकि हम इसे पूरी तरह से छोड़ सकें

अंतिम प्रश्न यहाँ:

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)

बिना किसी समान पंक्तियों के, आपके प्रश्न के रिकॉर्ड के समान ही आउटपुट करना चाहिए
कुछ वीडियो डुप्लीकेट cameras के बीच एक से अनेक संबंधों के कारण अभी भी मौजूद रहेंगे और events

अब बात करते हैं,
आपको वीडियो पर कुछ संबंधों को परिभाषित करना होगा मॉडल

// 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');
}

वीडियो नियंत्रक और खोज स्वयं कार्य करता है

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 प्रत्येक वीडियो को एक रिकॉर्ड (pk पर आधारित) के रूप में मानेगा, जिसका अर्थ है कि सभी वीडियो डुप्लीकेट हटा दिए गए हैं। आपके पास एकल वीडियो होंगे, प्रत्येक में कई ईवेंट होंगे ताकि आप 'event_type' का उपयोग न कर सकें और 'event_timestamp' दृश्य में लेकिन आप वीडियो . के अंदर कुछ गेटर्स घोषित कर सकते हैं उस जानकारी को दिखाने के लिए मॉडल:

public function getEventTypes(){
    return implode(', ', ArrayHelper::getColumn($this->events, 'event_type'));
}

public function getEventTimestamps(){
    return implode(', ', ArrayHelper::getColumn($this->events, 'event_timestamp'));
}

और दृश्य उपयोग:

<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],
        'idvideo',
        'eventTypes',
        'eventTimestamps',
        'filelocation',
        //['class' => 'yii\grid\ActionColumn'],
    ],
]); ?>

संपादित करें :
अगर आप वीडियो को डुप्लीकेट रखना चाहते हैं, तो events से दो कॉलम घोषित करें अंदर वीडियो मॉडल

public $event_type, $event_timestamp;

मूल GridView रखें सेटअप करें, और एक select जोड़ें और indexBy यह वीडियो नियंत्रक . के अंदर की क्वेरी के लिए :

$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++);
    });

अपडेट करें

एक सीधा staff Video . के संबंध में वर्तमान में कुछ समस्या है क्योंकि वह इससे एक से अधिक टेबल दूर है। इसके बारे में एक समस्या है यहां

हालांकि, आप staff . जोड़ते हैं तालिका को ईवेंट . से लिंक करके मॉडल,

public function getStaff() {
    return $this->hasOne(Staff::className(), ['idreceptionist' => 'staff_idreceptionist']);
}

जो आपको इस तरह क्वेरी करने की अनुमति देगा:

->joinWith(['camera', 'events', 'events.staff'], true, 'INNER JOIN')

फ़िल्टर करना नियंत्रक, दृश्य और SarchModel . पर कुछ छोटे अपडेट की आवश्यकता होगी
यहां एक न्यूनतम कार्यान्वयन है:

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;
    }
}

नियंत्रक:

public function actionIndex() {
    $searchModel = new VideoSearch();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

    return $this->render('test', [
        'searchModel'  => $searchModel,
        'dataProvider' => $dataProvider,
    ]);
}

और दृश्य

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. एंटिटी फ्रेमवर्क कोड-पहले स्टार्टअप पर बहुत धीमा

  2. स्प्रिंग जेपीए में सटीक मिलान रिकॉर्ड कैसे प्राप्त करें @Query

  3. Percona XtraDB क्लस्टर Kubernetes ऑपरेटर का अवलोकन

  4. स्कैला का उपयोग करके मैं एक MySQL डेटाबेस से कैसे जुड़ सकता हूं?

  5. यह एसक्यूएल गलत कैसे हो सकता है? मैं क्या नहीं देख रहा हूँ?