Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] Sumowanie po wierszach
Forum PHP.pl > Forum > Bazy danych
Glaser
Witam, na wstępie chciałbym zaznaczyć iz jeżeli chodzi o sql jestem zupełnym nowicjuszem.

Moja tabela wygląda tak:

  1. CREATE TABLE work_time(
  2. id int PRIMARY KEY,
  3. week int,
  4. day_of_week varchar(20),
  5. start timestamp,
  6. finish timestamp);




id week day_of_week start finish //tu przy zapytaniu tworzyłaby się nowa kolumna, powiedzmy "czas"
1 1 poniedzialek 2013-08-20 06:00:00 2013-08-20 12:00:00 //6
2 1 wtorek 2013-08-20 06:30:00 2013-08-20 14:00:00 //13,5 (jako iż 6+7,5)
...



Czy jest możliwość wyświetlania w outpucie widoku kolejno dodanych do siebie godzin tzn. powiedzmy, że pierwszego dnia czas pracy wyniósł 6h, wiec "za" finish byloby 6, we wtorek 7,5 wiec za finish gdzie id=2 byloby 13,5 itd. Myslałem, aby zrobić to w pętli, ale po zapoznaniu się z formułami pętli w mysql, nadal jestem w kropce.

Z góry dziękuję za pomoc

P.S Wybaczcie wygląd przykładowej tabeli, ale edytor zjada spacje
trueblue
Spróbuj:
  1. SELECT id,week,day_of_week,start,finish,IF(id<>@id,(SELECT @czas_pracy:=0),0),IF(id<>@id,(SELECT @id:=id),0),(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0,@id:=0)
Glaser
Otrzymuję błąd
Error Code: 1248. Every derived table must have its own alias
trueblue
  1. SELECT id,week,day_of_week,start,finish,IF(id<>@id,(SELECT @czas_pracy:=0),0),IF(id<>@id,(SELECT @id:=id),0),(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0,@id:=0) AS tmp
Glaser
Dziękuję za odpowiedź, ale niestety nie działa tzn. w każdym wierszu 'czas pracy' wyswietla mi ilosc przepracowanych godzin w danym dniu, jednak nie sumuje tych godzin z góry do dołu. Wygląda to tak (to wiedziałem jak zrobić):


start finish czas pracy
8 16 8
6 16 10
9 19 10



a mi chodziło o to, aby wyglądało tak:
start finish czas pracy
8 16 8
6 16 18
9 19 28

trueblue
  1. SELECT id,week,day_of_week,start,finish,(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START
  2. ))/3600+@czas_pracy) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp
Glaser
Bardzo dziękuję, działa biggrin.gif
Z ciekawości, jako laik spytam:
1)@czaspracy - '@' oznacza w tym przypadku wprowadzenie czegoś w stylu tymczasowej zmiennej?
2)Zastanawiam się też, czy można zmienić format wyświetlania tych godzin tzn aktualnie jest 18.000000000, a chciałbym, aby było 18.
Tak samo np. mam kolumne start i jest w niej data w formacie yyyy-mm-dd to czy można w jednym zapytaniu wyswietlić całą tabelę ze zmienioną data w formacie dd-mm-yyyy. Samą date jako zapytanie wiem jak zmienić (select date_format), ale nie działa mi to dla całej tabeli.

Z góry dziękuję za odpowiedź i pozdrawiam
trueblue
ad.1 http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
ad.2 http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html
ad.3 Tak jak piszesz, DATE_FORMAT, czyli SELECT DATE_FORMAT(finish,tu_format) FROM...
Glaser
Dziękuję za wskazówki. Z formatowaniem daty i godziny chyba sobie poradziłem:

  1.  
  2. SELECT id, week, day_of_week, start, date_format(finish, '%d/%m/%Y %h:%i:%s' ) AS finish FROM work_time;


Jednakże, nie radzę sobie z formatowaniem lizb. Używam funkcji convert(), konwertuje na signed lub decimal, jednak nic się nie dzieje. Czy gdzieś popełniłem błąd w składni czy cos innego mam zupełnie źle?

  1. SELECT id,week,day_of_week,start,finish,(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp,(SELECT convert(@czas_pracy, signed)) AS czas_pracy;
trueblue
Konwertować powinieneś ten fragment:
  1. (@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy)

To co dodałeś na końcu zapytania usuń.
Glaser
Dziękuję bardzo, działa smile.gif

  1. SELECT id,week,day_of_week,start,finish,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp;


Wynalazłem kolejny problem. Nie mogę poradzić sobie z połączeniem wyswietlania sumy pracy w jednym dniu i sumowaniu tych godzin tak jak jest wyżej. Chciałbym, żeby po kolumnie czas_pracy, była kolumna czas, a w niej ilosc godzin przepracowanych w danym dniu.
W przypadku 1 wyrzuca mi błąd: Subquery returns more than 1 row

  1. SELECT id,week,day_of_week,start,finish,(SELECT sum(@czas:=(hour(finish-start))) AS czas FROM work_time GROUP BY id),(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy
  2. FROM work_time,(SELECT @czas_pracy:=0) AS tmp;


Natomiast w 2 przypadku próbowałem użyc union, powiela mi wyniki tabeli (robi drugą pod spodem), bez drugiego id=1, tylko po id=10, następuje id=2 i w tych powielonych wierszach od id=2 do id=10 wyswietla ilosc przepracowanych godzin w danym dniu.

  1. SELECT id,week,day_of_week,start,finish,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp UNION DISTINCT SELECT id,week,day_of_week,start,finish, sum(hour(finish-start)) AS czas FROM work_time GROUP BY id;


Mam do tej sytuacji ogólne pytanie, czy jest w ogóle możliwe takie połączenie dwóch selectów? Szukałem w google, znalazłem tylko informacje odnośnie łączenia n-tabel.

Z góry dziękuje za pomoc i pozdrawiam
trueblue
W danym dniu, ale również narastająco?
Glaser
Nie, wystarczy, że obok wyniku tego zapytania
  1. SELECT id,week,day_of_week,start,finish,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp;


pojawi się kolumna czas i będzie w niej wyświetlona ilość godzin przepracowanych w danym dniu
trueblue
Możesz to zrobić korzystając z podzapytania jako źródła kolumny lub podzapytania w klauzuli FROM.
Glaser
Próbuję zastosować się do tych rad, ale nie bardzo je rozumiem. Mógłbym prosić o troche większą podpowiedź? Z tego co zrozumiałem, powinienem umiejscowić w odpowiedniej formie

  1. (sum(hour(finish-start)) AS czas FROM work_time GROUP BY id)


za selectem, tam gdzie kolumny tak? Gdy tak wstawiam, to podkreśla mi 'as', jakby go tam nie miało być
Glaser
Wydaje mi się, że zrobiłem analogicznie u siebie, jednak teraz podkreśla mi drugie AS... sad.gif

  1. SELECT id,week,day_of_week,start,finish,(SELECT sum(finish-start) FROM work_time) AS czas FROM work_time GROUP BY czas,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed))[u] AS[/u] czas_pracy
  2. FROM work_time,(SELECT @czas_pracy:=0) AS tmp;
trueblue
  1. SELECT id,week,day_of_week,start,finish,(SELECT SUM(TIME_TO_SEC(TIMEDIFF(finish,start)))/3600 FROM work_time AS wt WHERE DATE(wt.start)=DATE(start) GROUP BY DATE(wt.start)) AS czas,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp;
Glaser
Niestety, ten sam błąd co u mnie wcześniej ;( Subquery returns more than 1 row
trueblue
  1. SELECT id,week,day_of_week,start,finish,(SELECT SUM(TIME_TO_SEC(TIMEDIFF(finish,start)))/3600 FROM work_time AS wt WHERE DATE(wt.start)=DATE(start)) AS czas,(convert(@czas_pracy:=TIME_TO_SEC(TIMEDIFF(finish,START))/3600+@czas_pracy,signed)) AS czas_pracy FROM work_time,(SELECT @czas_pracy:=0) AS tmp;
Glaser
Prawie działa, z jednym małym ale. W każdym wierszu wyświetla 8 godzin, co nie jest prawdą. Domyślam się że problem leży w grupowaniu? Próbowałem rozwiązać to samemu, niestety bez efektów
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.