Jak taki efekt uzyskać za pomocą jednego zapytania

0

Mam taki problem mam algorytm, który liczy mi średnią dawkę na dzień brania substancji x i teraz ten algorym sprawdza pierwszy dzień zaczecia brania tej substancji i od tego pierwszego dnia liczy dane do dzisiajszej daty i liczy jaka dawka byłą średnia na dzień i teraz ja mam taki algorytm

 $data1 = "2009-04-01" . poczatek_dnia;
    $data2 = $data2 . poczatek_dnia;
    //print $data2;
    $data = explode(" ",$data2);
    $data22 = explode("-",$data[0]);
    $data33 = explode(":",$data[1]);
    $dni = mktime($data33[0],$data33[1],$data33[2],$data22[1],$data22[2],$data22[0]);
    $dni2 = $dni;
    $data = new data;
    $roznica = $data->oblicz_liczbe_dni($data1,$data2);
    //print $roznica;
    $data11 = $data1;
    for ($i=0;$i <=$roznica;$i++) {
      $data11 = date("Y-m-d H:i:s",$dni-86400);
      $data111 = date("Y-m-d H:i:s",$dni);
      $dni -= 86400;
      $dd = $baza->query("select porcja from spozycie where id_substancji = '$id_substancji' and data >= '$data11'  and data <= '$data111' ");
      $dd = mysqli_fetch_array($dd);
      if ($dd[0] == "") {
	$data11 = date("Y-m-d H:i:s",$dni);
	break;
      }
      
    }
    $data222 = $dni2 + 86400;
    
    $data222 = date("Y-m-d H:i:s",$data222);
    //print $data2;
    $suma2 = $baza->query("select sum(porcja) from spozycie where id_substancji = '$id_substancji' and  data <= '$data222'  and data >= '$data11'");
    $suma2 = mysqli_fetch_array($suma2);
    return array($suma2[0],$i+1);

Zasada działania tego algorytmu jest następująca sprawdza czy w danymdniu była ta susbatncja brana jeżeli tak to idzie jeszcze aż do momentu kiedy nie było tej substancji branej no i zapisuje sumę liczby dni do zmiennej i potem w zapytaniu oblicza średnią braną na dzień.

0

Podziel ten kod na funkcje, ponazywaj po ludzku zmienne ($dni2 ?), używaj klasy http://php.net/manual/en/class.datetime.php
Sformatuj ten kod ładniej i wtedy ponów pytanie, bo teraz troszkę szkoda czasu na analizowanie takiego potworka.

Poza tym funkcja "oblicz_liczbe_dni" jest juz dostępna w SPL np za pomocą DateInterval
Nie stosuj polskich nazwa zmiennych/funkcji.
W zależności od reszty kodu - możliwe że masz podatność na SQL Injection
86400 - zamień na stałą.

0
    $data_rozpoczecia = "2009-04-01" . poczatek_dnia;
    $data_rozpoczecia2 = $data_rozpoczecia2 . poczatek_dnia;
    //print $data2;
    $data_podzial = explode(" ",$data_rozpoczecia2);
    $data_podzial2 = explode("-", $data_podzial[0]);
    $data_podzial3 = explode(":", $data_podzial[1]);
    $sekundy = mktime( $data_podzial3[0], $data_podzial3[1], $data_podzial3[2],$data_podzial2[1],$data_podzial2[2],$data_podzial2[0]);
    $sekundy2 = $sekundy;
    $data = new data;
    $roznica = $data->oblicz_liczbe_dni($data_rozpoczecia,$data_rozpoczecia2);
    //print $roznica;
    $data_tymczasowa = $data_rozpoczecia;
    for ($i=0;$i <=$roznica;$i++) {
       $data_tymczasowa = date("Y-m-d H:i:s",$sekundy-86400);
       $data_tymczasowa2 = date("Y-m-d H:i:s",$sekundy);
       $sekundy -= 86400;
       $wynik = $baza->query("select porcja from spozycie where id_substancji = '$id_substancji' and data >= '$data_tymczasowa'  and data <=   '$data_tymczasowa2' ");
      $wynik = mysqli_fetch_array($wynik);
      if ($wynik[0] == "") {
         $data_tymczasowa  = date("Y-m-d H:i:s",$sekundy);
         break;
      }
 
    }
    $data_sumowanie = $sekundy2 + 86400;
 
   $data_sumowanie = date("Y-m-d H:i:s",$data_sumowanie);
    //print $data2;
    $suma2 = $baza->query("select sum(porcja) from spozycie where id_substancji = '$id_substancji' and  data <= '$data_sumowanie'  and data >= '$data_tymczasowa'");
    $suma2 = mysqli_fetch_array($suma2);
    return array($suma2[0],$i+1);

Nie ma sensu dzielić tego kodu na funkcje bo ten kod to jest jedna funkcja.

0

Wg mnie ta funkcja zdecydowanie robi zbyt wiele rzeczy. Poza tym nie wiadomo nawet jak parametry trafiają do tego kodu no i po co Ci takie rozbijanie daty za pomocą explode'a? Kod nadal jest brzydki i masz sporo zbędnych rzeczy (po co nam komentarze?). Nazewnictwo zmiennych powoduje że ciężko się czyta taki kod - nazwij to po ludzku - to że Ty teraz wiesz o co Ci chodzi to nic nie zmienia. Za miesiąc lub dwa nikt nie dojdzie po co Ci były zmienne. Dlaczego nie korzystasz z wbudowanych funkcji tylko piszesz swoje?
http://php.net/manual/en/datetime.gettimestamp.php -

Na górze masz Twój kod i sposób wyciągania czasu, a niżej jest "mój sposób" :P

$data_rozpoczecia = "2009-04-01 00:00:00" ;
    
    $data_podzial = explode(" ",$data_rozpoczecia);
    $data_podzial2 = explode("-", $data_podzial[0]);
    $data_podzial3 = explode(":", $data_podzial[1]);
    $sekundy = mktime( $data_podzial3[0], $data_podzial3[1], $data_podzial3[2],$data_podzial2[1],$data_podzial2[2],$data_podzial2[0]);
    echo 'Stare sekundy: '. $sekundy.'<br/>';


    $dateStart = new DateTime("2009-04-01 00:00:00");
    echo '<br/>Nowe sekundy: '. $dateStart->getTimestamp();

Pamiętaj - czym czytelniejszy będzie Twój kod, tym łatwiej będzie debugować oraz rozwijać.

0
select pierwszy
union
select drugi
$wynik = $baza->query("select porcja, trunc(data) data from spozycie where id_substancji = '$id_substancji' and data >= '$data_rozpoczecia'  and data <=   '$data_rozpoczecia2'  order by trunc(data) ");

masz porcję na dzień w przedziale od data_rozpoczecia do data_rozpoczecia2

0

Skoro potrzebne jest rozwiazanie problemu - służę poradą:
Najpierw założenia (skoryguj jak coś będzie nie tak)

  1. W bazie danych przechowujesz datę oraz ID branej substancji (jako pojedynczy rekord)
Zasada działania tego algorytmu jest następująca sprawdza czy w danymdniu była ta susbatncja brana jeżeli tak to idzie jeszcze aż do momentu kiedy nie było tej substancji branej no i zapisuje sumę liczby dni do zmiennej i potem w zapytaniu oblicza średnią braną na dzień.
  1. W bazie danych mając tylko takie dane jak opisałem wyżej(wynika to z Twoich zapytań SQL) - możesz od razu pobrać przedział wartości date BETWEEN ... mając to sumujesz ilość rekordów COUNT(spozycie_id) (albo *) i w sqlu wykonujesz DATEDIFF (dzięki czemu już w sql'u obliczysz ile dni różni te daty) i tyle.

Po co Ci suma liczby dni?
Podaj może jakieś przykładowe dane np
$dataStart = "2017-01-01 00:00:00";
$dataEnd = "2017-01-05 00:00:00";
$substanceId = 25
oraz efekt jaki chcesz uzyskać dla tych danych.

0

No więc tak, skonstruowałęm anstępujące zapytanie

select DATEDIFF(data,'$data_new') AS DiffDate, porcja, data from spozycie where id_substancji='$id_drugs' and data <= '$data_new' group by data

Nie wiem czy dobrze

I teraz jak to umieściłęm w funkcji laravela DB::select to zwraca następujący błąd.

Syntax error or access violation: 1055 'uzywki2.spozycie.porcja' isn't in GROUP BY

Więc użyłem funkcji DB::table

No i tak użyłem

DB::table('spozycie')->select(DB::raw("DATEDIFF(data,'$data_new') AS DiffDate, porcja, data"))->where('id_substancji', '=', $id_drugs)->groupBy('data');

To mi zwraca błąd.Undefined property: Illuminate\Database\MySqlConnection::$DiffDate

0

Już sobie z tym poradziłem trzeba było zmienić w pliku /conig/database.php
z 'strict' => true
na 'strict' => false

0

A nie można tak:

select
    id_substancji
    ,sum(porcja)/count(distinct date(data)) as `srednia dawka na dzien`
from
    spozycie
where 
    data >= '2016-12-31 11:00:00'
    and id_substancji=1
group by 
    id_substancji

Fiddle: http://sqlfiddle.com/#!9/16b21/10/0

1 użytkowników online, w tym zalogowanych: 0, gości: 1