Odczytanie stanu wypożyczeń książek z bazy SQL

0

Cześć.
Mam bardzo prostą bazę książek. Wypożyczenie książki powoduje wpis w tabeli WYPOZYCZENIA indeksu użytkownika, który wypożyczył, timestamp wypożyczenia oraz status wpisany jako 0. Po oddaniu książki jest wpisywany w tabeli WYPOZYCZENIA timestamp oraz status zmieniony na 1.

W jaki sposób „wyciągnąć” tabeli ostatnie statusy książek?
Przykładowo mam:

| book | user | stan|   time           |
|   1  |   1  |  0  | 2019-11-04 15:31 |
|   2  |   1  |  0  | 2019-11-04 15:32 |
|   3  |   4  |  0  | 2019-11-04 15:33 |
|   1  |   0  |  1  | 2019-11-04 15:37 |
|   1  |   5  |  0  | 2019-11-04 15:39 |
|   3  |   0  |  1  | 2019-11-04 15:39 |

wiersz 1 - książkę nr 1 wypożyczył użytkownik nr 1, co spowodowało wpisanie stanu = 0
w wierszu 4 książka nr 1 została zwrócona co spowodowało dodanie wpisu i ustawienie stanu = 1
w wierszu 5 książka nr 1 znów została wypożyczona, tym razem użytkownikowi nr 5 => zapisany stan = 0

W jaki sposób „wyciągnąć" tylko wypożyczone książki? Czyli wg powyższego przykładu w odpowiedzi na zapytanie powinny pokazać się tylko 2 pozycje:
książka numer 2 wypożyczona użytkownikowi 1 o 2019-11-04 15:32
książka numer 1 wypożyczona użytkownikowi 5 o 2019-11-04 15:39.

Da się to zrobić 1 selectem?

0

Nie znam się na SQL-u dobrze, ale moim zdaniem mogłoby to wyglądać tak:

  1. wyciągasz wszystkie książki;
  2. potem grupujesz je według numeru;
  3. potem sortujesz je w każdej grupie (tzn. oddzielnie od innych grup) według daty;
  4. potem bierzesz top 1 (czy jakoś tak) z każdej grupy.
1

Po pierwsze - masz błąd (wprawdzie to tylko przykład i pewnie zwykła omyłka, ale i tak zaznaczę/wyjaśnię) - w wierszu pierwszym książkę pożycza user 1, ale w wierszu 4 oddaje ją ktoś inny (user 0).

A odpowiadając na Twoje pytanie - zakładam, że dane w time są zgodne z rzeczywistością oraz że zachowują chronologię. W takim razie, czym jest wypożyczona książka? Zgodnie z Twoją tabelką oraz wyjaśnieniami, wypożyczona książka to taka, która posiada ostatni wpis (zgodnie z chronologią dostarczoną przez kolumnę time) z wartością stan ustawioną na 1, prawda? Mam nadzieję, że teraz masz jakąś wskazówkę, jak podejść do tematu ;)

P.S. staraj się konsekwentnie przypisywać nazwy zmiennym/kolumnom w tabeli. Teraz masz miks polsko-angielski - zarówno time jak i stan. Większość nazw jest po angielsku, więc bardziej by pasowała nazwa state.

1

Na przykłada tak .. albo jak nie chcesz używać CTE to sobie to zagnieźdź:

WITH LastDate
as 
(SELECT book, MAX(time) LatestTime 
FROM Wypozyczenia 
GROUPB BY book)

SELECT book, user, stan, time
FROM Wypozycznia w
INNER JOIN LastDate l
ON w.book = l.book
AND w.time = l.LatestTime 
WHERE w.stan = 0
0

@cerrato:
Nie mam błędu. W 1. wierszu wypożycza user 1 i oddaje ją w wierszu 4. Dlatego wpisane jest zero, bo w formularzu oddawania książki mam tylko pole na wpisanie numeru zwracanej książki. Nie ma informacji o oddającym, bo dla mnie nie ma znaczenia kto oddaje (w uproszczonym modelu jest to oczywiste, że zwraca ją user 1). A z braku informacji z formularza wsadzam po prostu 0 :-).

Dane są ułożone chronologicznie.
Nie do końca. Stan 1 oznacza, że książka „jest na stanie” i można ją wypożyczyć, stan 0 oznacza, że książki jest wypożyczona. W formularzu wypożyczenie mam 2 pola: nr książki oraz nr użytkownika. Po kliknięciu Wyślij do tabeli WYPOZYCZENIA dodawany jest rekord ze stanem ustawionym na zero dla książki o podanym numerze i użytkownika o podanym numerze.
Formularz zwrotu posiada tylko pole na wpisanie nr książki. Z tego formularza w bazie zapisuke numer książki, użytkownika = 0 i stan = 1.

Mam nadzieję, że teraz jasno opisałem :-).

PS.: Słuszna uwaga, dzięki.

@BlackBad:
Coś mi nie działa :-(. W 3. wierszu otwierasz {, a nie ma nigdzie zamknięcia.

0

Literówka poprawiłem ją już. Chyba miałeś otwarte okno bo jak zacząłeś pisać posta było już poprawnie.
Co do tłumaczenia Twojej logiki to tak pokrętna bym powiedział. Czy możesz mieć więcej sztuk tej samej książki ? Jeśli zakładamy, że masz po 1 sztuce każdej książki i logujesz najpierw wypożyczenie a później zwrot (czyli zgodnie z rzeczywistością) to odpowiedź brzmi "Tak masz dane chronologicznie".

0

@BlackBad:
jeszcze masz literówkę w GROUPB. Czy to zadziała w MySQL? Bo mi wywala błędy.
Każda książka tylko w jednym egzemplarzu. Loguję najpierw wypożyczenia, później zwroty, czyli chronologicznie.

0

Zależy jaka wersja zdaje się (tylko rzuciłem okiem w googlu) No ale to nie uzywaj CTE i napisz tak:

SELECT book, user, stan, time
FROM Wypozycznia w
INNER JOIN (SELECT book, MAX(time) LatestTime 
                   FROM Wypozyczenia 
                   GROUP BY book) l
ON w.book = l.book
AND w.time = l.LatestTime 
WHERE w.stan = 0
0

Bym liczył stan na bieżąco ...
Wpisz:
Wydano, UserId, BookID
Przyjęto, UserId, BookID
Wtedy kontrolujesz każdą książkę nawet jak masz kilka egzemplarzy.
Stan na dzień zliczasz SQL'em
Mam tak zrobione w programie magazynowym, 300 tyś transakcji dziennie, beż problemów zlicza stan magazynu na dowolny dzień (w ramach roku)

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