За последние 24 часа нас посетили 22296 программистов и 1023 робота. Сейчас ищут 654 программиста ...

Как разделить один столбец на два, по условию?

Тема в разделе "PHP и базы данных", создана пользователем Artur_hopf, 5 дек 2018.

  1. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Добрый день. Есть таблица такого вида:

    Код (Text):
    1.  
    2. Status | Duration
    3. 1      | 20
    4. 1      | 15
    5. 0      | 13
    Нужно из этой таблицы другую, где бы было два столбца Duration отличающиеся по статусу.
    Выглядеть должно например так:
    Код (Text):
    1.  
    2. Duration1 | Duration2
    3. 20        | 13
    4. 15        | NULL
    То есть если в одном столбце количество значений не совпадает, писало NULL.
    Сейчас я делаю тупо два запроса где отличаются WHERE Status:
    PHP:
    1. SELECT Duration
    2. FROM database
    3. WHERE Status = 1
    4.  
    5. SELECT Duration
    6. FROM database
    7. WHERE Status = 0
    Можно одним запросом же?
     
  2. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Дошел прока до такого, но результат не такой какой хочется:
    Код (Text):
    1.  
    2. SELECT
    3. case when Status = 1 then Duration end as Duration1,
    4. case when Status = 0 then Duration end as Duration2
    5. FROM database
    На выходе получаю:
    Код (Text):
    1. Duration1 | Duration2
    2. 20        | NULL
    3. 15        | NULL
    4. NULL      |13
    Что я не доделал, подскажите пожалуйста.
     
  3. villiwalla

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

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Полагаю тебе нужен UNION
     
  4. Valick

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

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Очень трудно подобрать цензурные слова, глядя на то, что вы творите.
    --- Добавлено ---
    полагаю и вам не мешало бы книжек почитать :)
     
  5. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @Valick я же за помощью тут пишу, а не что бы показать как я умею.
     
  6. villiwalla

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

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Возможно, не отрицая, но я слышал такую формулировку "Оператор UNION позволяет обединить две однотипных выборки. Эти выборки могут быть из разных таблиц или из одной и той же таблицы."

    Что же вы тогда предлагаете?
     
  7. Valick

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

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Я как бы догадался, что речь о слухах (тут и к бабке не пойду), поэтому и предложил прочесть как и для чего используется конструкция UNION.
    Не заниматься оккультизмом и не ставить перед собой противоестественные для реляционной БД задачи.
    Можно конечно использовать "суррогатный" ключ по которому потом объединить эти выборки, но по сути это ересь.
    И если возникают подобного рода потребности, значит проблема в архитектуре БД.
     
  8. villiwalla

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

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Ну от вроде, не пытается их сопоставить, а просто, одну колонку разделить на 2. Мб это и хрень, но всё же.
     
  9. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @Valick вооот, теперь вы ответили, мол так не делается. Спасибо за ответ =)
     
  10. Valick

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

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @Artur_hopf, на форуме много раз говорили, что надо озвучивать саму проблему, а не то как ты сам видишь решение.
    P.S. У Арбенина есть строки: "
    День дожидался темноты,
    Жизнь начиналась с середины"
    Давайте середину оставим Арбенину, а проблему описывать с самого начала.
     
    #10 Valick, 6 дек 2018
    Последнее редактирование: 6 дек 2018
  11. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @Valick Проблему я решил. А надо было потянуть значения с Status = 1 и с Status = 0. Потом суммировать каждую строку с соседней, чтобы получить полный цикл времени в секундах. Duration это время в секундах. Там где оно равно нулю это сколько времени понадобилось в начале, единица это сколько времени занял сам процесс. Итого получаем полный цикл жизни. Потом мне надо было вывести среднеквадратичное отклонение. И в конце проигнорировать значения которые выходят за отклонения.

    Я все это сделал, просто использовал два запроса.
    Вот в итоге за один день разобрался:
    PHP:
    1. public function getDuration($id){
    2.    $query0 = new Query;
    3.    $query1 = new Query;
    4.    $time = ModelView1::timeShift();
    5.    $oid = ModelView1::oid();
    6.  
    7.    $query0->select('Duration');
    8.    $query0->from('database AS RF');
    9.    $query0->leftjoin('database2 AS RR', 'RF.Reader = RR.Oid');
    10.    $query0->where(['RR.Asset' => $oid[$id]]);
    11.    $query0->andWhere(['RF.Status' => 0]);
    12.     $query0->andWhere("RF.Date BETWEEN DATEADD(hour,".$time[0].", DATEDIFF(dd, 0, GETDATE()))
    13. AND DATEADD(hour,".$time[1].", DATEDIFF(dd, 0, GETDATE()))");
    14.     $query0->orderBy(['RF.Date' => SORT_DESC]);
    15.     $status0 = $query0->column();
    16.  
    17.    $query1->select('Duration');
    18.    $query1->from('database AS RF');
    19.    $query1->leftjoin('database2 AS RR', 'RF.Reader = RR.Oid');
    20.    $query1->where(['RR.Asset' => $oid[$id]]);
    21.    $query1->andWhere(['RF.Status' => 1]);
    22.    $query1->andWhere("RF.Date BETWEEN DATEADD(hour,".$time[0].", DATEDIFF(dd, 0, GETDATE()))
    23. AND DATEADD(hour,".$time[1].", DATEDIFF(dd, 0, GETDATE()))");
    24.    $query1->orderBy(['RF.Date' => SORT_DESC]);
    25.    $status1 = $query1->column();
    26.  
    27.    if(count($status1) > 0){
    28.      foreach($status1 as $key=>$val) {
    29.          if(isset($status0[$key])){
    30.              $status1[$key] += $status0[$key];
    31.         }else{
    32.             $status1[$key] += 0;
    33.       }
    34.    }
    35.      return ModelView1::createPointVTC($status1);
    36.   }else{
    37.      return 0;
    38.      }
    39. }
    40.  
    41. public function createPointVTC($status1){
    42.     $sum = array_sum($status1);
    43.     $mean = $sum / count($status1);
    44.     $sqrt = ModelView1::arraySqrt($status1, $mean);
    45.     $plus = $mean + $sqrt;
    46.     $minus = $mean - $sqrt;
    47.     $filter = array_filter($status1, function($k) use ($plus, $minus) {
    48.         return $k > $plus || $k < $minus;
    49.      });
    50.     if(count($filter) > 0){
    51.        $sumFilter = array_sum($filter);
    52.      }else{
    53.        $sumFilter = $sum;
    54.      }
    55.     $sr_rms = ($sum - $sumFilter)/(count($status1) - count($filter));
    56.        return round($sr_rms);
    57.     }
    58.  
    59. public function arraySqrt($arr, $mean){
    60.     $var = 0.0;
    61.     foreach ($arr as $i){
    62.        $var += pow($i - $mean, 2);
    63.     }
    64.     $size = count($arr) - 1;
    65.      return (float) sqrt($var)/sqrt($size);
    66. }
     
  12. Valick

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

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    эти соседние строки я так понимаю не связаны никаким ключём, а исключительно "по щучьему веленью, по моему хотенью..."
    сдаётся мне как лиса и сыр "басню сильно сократили", и тот кто создавал бд слыхом не слыхивал про нормализацию данных
    при грамотной архитектуре бд вся задача должна решаться на уровне СУРБД