За последние 24 часа нас посетили 22386 программистов и 1024 робота. Сейчас ищут 686 программистов ...

Как использовать UNION ALL в yii2?

Тема в разделе "Yii", создана пользователем Artur_hopf, 6 фев 2019.

  1. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Добрый день в SSMS написал такой запрос с двумя id:
    Код (Text):
    1.  
    2. SELECT id, date
    3. FROM (SELECT TOP(1) RR.Asset AS id, RF.Date AS date
    4. FROM  database1 AS RF
    5. LEFT JOIN database2  AS RR ON (RF.Reader = RR.Oid)
    6. WHERE RR.Asset =  '93e8fecb-8782-4357-b0fc-75c147594f50'
    7. ORDER BY RF.Date desc) AS a
    8. UNION ALL
    9. SELECT id, date
    10. FROM (SELECT TOP(1) RR.Asset AS id, RF.Date AS date
    11. FROM database1 AS RF
    12. LEFT JOIN database2 AS RR ON (RF.Reader = RR.Oid)
    13. WHERE RR.Asset =  'b8bbc8b6-f36f-434f-9574-91cdaf1e708d'
    14. ORDER BY RF.Date desc) AS b
    Теперь переношу его в yii2 чтобы циклом проходилось по массиву c id, дошел до этого. Пока без цикла, вручную:
    PHP:
    1. $query = new Query;
    2. $id = ModelConnection::id();
    3. $subQuery = (new Query())
    4.      ->select('RR.Asset AS id, RF.Date AS date')
    5.      ->from('database1 AS RF')
    6.      ->leftjoin('database2 AS RR', 'RF.Reader = RR.Oid')
    7.      ->limit(1)
    8.      ->where(['RR.Asset' => $oid[0]])
    9.      ->orderBy(['RF.Date' => SORT_DESC]);
    10.  
    11. $subQuery1 = (new Query())
    12.      ->select('RR.Asset AS id, RF.Date AS date')
    13.      ->from('database1 AS RF')
    14.      ->leftjoin('database2 AS RR', 'RF.Reader = RR.Oid')
    15.      ->limit(1)
    16.      ->where(['RR.Asset' => $oid[1]])
    17.      ->orderBy(['RF.Date' => SORT_DESC]);
    18.  
    19. $query->select('id, date');
    20. $query->from(['a' => $subQuery->union($subQuery1)]);
    21. $result = $query->all();
    22. if(count($result) > 0){
    23.      return $result;
    24. }
    Подскажите как это грамотно засунуть в цикл, особенно интересует UNION, логика его примерно такая:

    $subQuery->union($subQuery1)->union($subQuery2)->union($subQuery3) и т.п.
     
  2. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    пока написал так:
    PHP:
    1. $query->select('id, date');
    2.  
    3. foreach($oid as $key => $val){
    4.     $sql = (new Query())
    5.     ->select('RR.Asset AS id, RF.Date AS date')
    6.     ->from('EAM_test.dbo.RFIDData AS RF')
    7.     ->leftjoin('EAM_test.dbo.RFIDReader AS RR', 'RF.Reader = RR.Oid')
    8.     ->limit(1)
    9.     ->where(['RR.Asset' => $val])
    10.     ->orderBy(['RF.Date' => SORT_DESC]);
    11.     $subQuery[$key] = $sql;
    12. }
    13.  
    14. $query->from([$subQuery[0]->union($subQuery[1])->union($subQuery[2])]);
    15. $result = $query->all();
    Может кто сталкивался как можно union в цикле вывести?
     
  3. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Написал вот такой костыль, может кто знает как без него?
    PHP:
    1. $query->select('id, date');
    2.  
    3. foreach($oid as $key => $val){
    4.     $subQuery[$key] = (new Query())
    5.     ->select('RR.Asset AS id, RF.Date AS date')
    6.     ->from('database1 AS RF')
    7.     ->leftjoin('database2 AS RR', 'RF.Reader = RR.Oid')
    8.     ->limit(1)
    9.     ->where(['RR.Asset' => $val])
    10.     ->orderBy(['RF.Date' => SORT_DESC]);
    11. }
    12.  
    13. if(count($oid) === 1){
    14.      $query->from([$subQuery[0]]);
    15. }
    16.  
    17. if(count($oid) === 2){
    18.     $query->from([$subQuery[0]->union($subQuery[1])]);
    19. }
    20.  
    21. if(count($oid) === 3){
    22.     $query->from([$subQuery[0]->union($subQuery[1])->union($subQuery[2])]);
    23. }
    24.  
    25. $result = $query->all();
    26. if(count($result) > 0){
    27.     return $result;
    28. }
     
  4. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    @Artur_hopf, попробуй так:
    PHP:
    1. $subQuery = false;
    2. foreach($oid as $key => $val){
    3.     $sql = (new Query())
    4.     ->select('RR.Asset AS id, RF.Date AS date')
    5.     ->from('EAM_test.dbo.RFIDData AS RF')
    6.     ->leftjoin('EAM_test.dbo.RFIDReader AS RR', 'RF.Reader = RR.Oid')
    7.     ->limit(1)
    8.     ->where(['RR.Asset' => $val])
    9.     ->orderBy(['RF.Date' => SORT_DESC]);
    10.     if($subQuery === false) {
    11.         $subQuery = $sql;
    12.     } else {
    13.         $subQuery = $subQuery->union($sql);
    14.     }
    15. }
    16. if($subQuery !== false) {
    17.     $query->select('id, date')->from($subQuery);
    18.     $result = $query->all();
    19. } else {
    20.     // ...
    21. }
     
  5. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @Sail не, так не получится. sql будет равен последнему запросу. Даже если сделать $sql[$key] непонятно как в union такой массив передать.
     
  6. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    Попробуйте, посмотрите, какой запрос подготовит предложенный вариант.
    Если действительно необходимо использовать $sql[$key], то допишите перед циклом инициализацию ($sql = []), а в цикле вместо $sql - $sql[$key].
    Основная идея в том, как формируется $subQuery.
     
  7. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @Sail там основная идея в том чтобы написать так =) :
    PHP:
    1. $query->select('id, date');
    2. $query->union($subQuery);
    3. $result=$query->all();
    И все, но у меня $subQuery массив и так не прокатит наверное.