Michał Moroz

Abecadło smoczątka, dziennik niecodzienny

Następna strona? - poprowadź mnie!

Postanowiłem nieco rozszerzyć ostatni wątek o pomysł, który ostatnio mnie nawiedził. Nadaje się on głównie dla osób, które są zainteresowane grzebaniem w kodzie swoich serwisów. I tutaj, na Joggerze na pewno nie jest ich mało.

Wszystkie modele opisane w poprzednim wpisie są modelami czysto generycznymi, w żaden sposób nie łączą się z akcjami użytkownika. Oczywiście, można to zmienić!

Dwie idee połączenia akcji użytkownika wraz z reakcją strony, które wpadły mi do głowy są względnie proste do zaimplementowania a mogę wnieść wiele do poszczególnych rodzajów oprogramowania.

Idea 1: Pierwsza nieodwiedzona strona.

Jedna z najprostszych idei, które mogą być bardzo pomocne w tworzeniu specjalizowanej listy linków dla użytkownika. Załóżmy, że istnieje lista stron od 1 do n. Gdzieś pomiędzy nimi znajduje się strona m, którą aktualnie odwiedza użytkownik. Użytkownik przechodzi następnie na stronę o. Wykonujemy następujące sprawdzenie:

  • Jeśli o < m, podajemy linka do m + 1 jako pierwszej nieodwiedzonej strony.
  • Jeśli o > m, m = o.

    • Jeśli chcemy być jeszcze bardziej poprawni, możemy sprawdzić, czy o > m + 1. Jeśli tak, możemy poinformować użytkownika, że pominął przy przeglądaniu odpowiednią ilość stron i zapytać, czy chce, abyśmy oznaczyli je za nieprzeczytane.
    • Uwaga - domyślnie oznaczamy je za przeczytane, bo jeśli ktoś już przeskakuje ileś stron, musi mieć ku temu powód!

Plusem tego rozwiązania jest to, że jeśli chcemy, da się je zaimplementować nawet w JavaScripcie, o ile dostarczymy mu numer aktualnej strony.

Zyskują na tym wielce fora, bo dostęp do wątków jest znacznie uproszczony. Nie jestem ich bywalcem, ale z tego, co wiem, w większości z nich stosowane są od dawna podobne mechanizmy. Jak bardzo pokrywają się z moim pomysłem - tego już nie powiem. :)

Problemy pojawiają się w przypadku stron, w których publikacje pojawiają się od najnowszej do najstarszej. W takim przypadku stosowanie powyższej idei mija się z celem - nieprzeczytana treść znaleźć się może nie tylko po jednej, ale po obu stronach listy.

Idea 2: Pozwól użytkownikowi zaznaczyć miejsce, do którego chciałby wrócić

Ta koncepcja jest jeszcze lepsza. W miejscach, gdzie różne wartościowe treści są rozrzucone wśród masy tych nieużytecznych, a jest ich stanowczo za dużo, aby bookmarkować je gdzieś w zewnętrznym serwisie, sami możemy postarać się o to, by zapewnić odpowiednią wygodę czytającym.

Jak? Na każdej ze stron dajemy dodatkowy przycisk, odpowiadający za akcję zapisania. Gdy przeglądamy listę stron, wszystkie zapisane strony z tej listy ukazują się jako linki. Jeśli założymy, że lista stron nie jest zbyt długa, aby mieć więcej niż kilka takich zakładek, użytkownik nie będzie potrzebował ich opisywania. Ale zamiast opisywania, skłaniam się ku innej formie. Niech zakładki mają kilka kolorów do wyboru.

Co dalej? Użytkownik może dostać własną stronę z zakładkami, jakie zrobił i małym wyjaśnieniem kontekstu (chciażby nazwa listy stron, w której dane zakładki się znajdują).

Kwestią sporną jest to, co powinno dziać się z taką zakładką po powróceniu na jej stronę. Przyzwyczajeni jesteśmy do manualnego usuwania wszelkich zakładek w przeglądarkach i specjalizowanych serwisach. Z drugiej strony logika podpowiada, że gdy ktoś wrócił na tą stronę, to w konkretnym celu i nie powinniśmy go zmuszać do dodatkowego klikania, tylko po to, by usunął tą zakładkę. Tą rzecz pozostawiam do przemyślenia ewentualnym implementatorom, specom od usability wyższej klasy ode mnie i wszystkim czytającym. ;)

Pomysł jest stary, jak stare są zakładki do książek. Ale chyba nikt jeszcze czegoś takiego sam z siebie nie zaimplementował w sieci. Głównym problemem tego rozwiązania jest z kolei bardzo łatwa możliwość zniszczenia całej jego używalności, jeśli tylko nie postaramy się utrzymać tego tak prostym, jak tylko można.

Mam nadzieję, że skłoniłem Cię do własnych refleksji. :)

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Następna strona? - usability, luźne przemyślenia

Cały czas w Internecie trafiasz na miejsca, gdzie treści jest tak wiele, że podzielona została na podstrony. Artykuły, archiwa newsów, fora, wszędzie. Jako użytkownik wymagasz wygody w poruszaniu się pomiędzy poszczególnymi stronami. Nic tak nie zniechęca, jak niemożność przejścia na następną stronę, kiedy znajdujesz się w środku ciekawego tekstu. Nie muszę wspominać, że już więcej tam nie wrócisz.

A jak to wygląda z drugiej strony? Tworzysz właśnie jakiś serwis i okazuje się, że koniecznością staje się zapewnienie dobrego poruszania się po podstronach. Konwencji jest kilka, niektóre są lepsze, niektóre gorsze, a część z nich niekoniecznie nadaje się do czegokolwiek.

Zasada numer jeden. Upraszczaj!

Chyba już nie raz widziałeś listy linków podobne do tego wzoru (jesteśmy na 8 stronie, nie jest ona linkiem):

Poprzednia 4 5 6 7 8 9 10 11 12 Następna

Zaczynamy od środka. Zastanów się, kto mógłby używać listy poprzednich i następnych czterech stron. Jeśli użytkownik jest zainteresowany, będzie czytał stronę po stronie. Jeśli nie jest, zamknie kartę od razu. Pomijając przeskakiwanie stron w celu przeszukiwania (bo od tego są inne narzędzia), najprawdopodobniej nie pozostaje żaden racjonalny powód do posługiwania się tymi linkami.

Doszliśmy do takiego modelu:

Poprzednia 8 Następna

Prostota. Wydaje mi się, że najlepszym układem przestrzennym dla tego modelu będzie Poprzednia po lewej stronie, Następna po prawej i 8 pośrodku. Duże marginesy pomiędzy poszczególnymi polami i wielkie, łatwo trafialne linki, najlepiej obramowane i z odpowiednim klikalnym paddingiem. Aby dopełnić dzieła i dać użytkownikowi świadomość objętości tekstu, dałbym jeszcze małą adnotację pośrodku, o, taką:

[ Poprzednia ]    Strona 8 z 13.    [ Następna ]

Ten model nadaje się do prawie wszystkich archiw, w których na jednej stronie jest dużo treści i nie potrzeba skakać gdzieś do określonych punktów.

Nie zmieniaj miejsca, w którym mają pojawić się linki

Zanim przejdę do analizy dalszych modeli, chcę uświadomić Ci jedną dość oczywistą prawdę, którą mało kto wykorzystuje.

Projektując swój model ustaw stałe szerokości dla poszczególnych linków. Dzięki czemu na każdej podstronie będą znajdować się w tej samej odległosci od brzegu ekranu, przez co użytkownik nie będzie musiał za każdym razem wyszukiwać od nowa miejsca, w które powinien kliknąć by przejść do określonej strony.

Jeśli dana strona nie istnieje, to pokaż pole z tekstem i oznacz je tak, aby użytkownik wiedział, że jest nieaktywne. Według mnie to najczytelniejsze i najestetyczniejsze rozwiązanie. Alternatywnie możesz skorzystać z visible: none.

Model drugi, artykuły

Ten model jest bardzo przydatny dla przydługich artykułów, które zazwyczaj mieszczą się na trzech, czterech stronach. W tym wypadku sprawa jest jeszcze prostsza, niż w poprzednim:

[ 1 ]   2   [ 3 ] [ 4 ]

Żadnych przycisków `następna' i `poprzednia'. Nie ma sensu ich stosować przy tak małej ilości podstron.

Model trzeci, fora

Forum bardzo akcentuje pierwszą i ostatnią stronę wątku. Dlatego to one będą podstawą w naszym modelu:

[  <<  ] [ Poprzednia ]   Strona 8 z 14   [ Następna ] [  >>  ]

Dlaczego nie posłużyłem się słownymi określeniami `pierwsza' i `ostatnia'? W ten sposób linki pierwszej i ostatniej strony nie kolidują z linkami poprzedniej i następnej, dzięki czemu nie trzeba wprowadzać kolejnych oznaczeń.

Oczywiście linkom pierwszej i ostatniej strony należy zapewnić odpowiednie rozmiary. Być może nawet nieco większe niż te stosowane do stron poprzedniej i następnej.

Model czwarty, linki do poprzednich i kolejnych stron

Owszem, na początku mocno skrytykowałem pomysł umieszczania linków do kolejnych i poprzednich stron, gdyż nie znalazłem dla nich rozsądnego użycia. Może jednak się okazać, że coś przeoczyłem, dlatego też podzielę się moimi przemyśleniami i na ten temat.

Weźmy model, który sktrytykowałem na początku i nieco go przetwórzmy zgodnie z powyższymi zasadami:

[ << ] [ Poprzednia ]   [ 4 ] [ 5 ] [ 6 ] [ 7 ] 8 [ 9 ] [ 10] [ 11] [ 12]   [ Następna ] [ >> ]

W wypadku, gdzie stron może być naprawdę dużo, a chcemy, aby użytkownik mógł się poruszać, zapewnijmy mu nieliniową skalę:

[ << ] [ Poprzednia ]   [   ] [ 1 ] [ 3 ] [ 5 ] [ 7 ] 8 [ 9 ] [ 11] [ 13] [ 18] [ 28]   [ Następna ] [ >> ]

W ten sposób użytkownik będzie mógł nieco szybciej przeskakiwać większe ilości stron. Można także pozbyć się duplikowania linków do poprzedniej i następnej strony.

Duplikaty linków

Jeśli musisz przedstawić linki prowadzące do poprzedniej i następnej strony w dwóch egzeplarzach to pokaż, że obie nawigacje są odrębnymi grupami funkcjonalnymi, bo w innym przypadku może to wprawić użytkownika w lekką konsternację, jak i każda inna redundancja.

I to by chyba były wszystkie moje luźne przemyślenia. Mam nadzieję, że skłonią Cię do chwili refleksji. ;)

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Morderca miniaturek

Miniaturkę możemy spotkać prawie wszędzie, gdyż dość dobrze nadaje się do prezentowania materiałów graficznych w sieci. Jej podstawową zaletą jest szybkość ładowania, to nie ulega wątpliwości. Dodatkowo, dzięki swym niewielkim rozmiarom użytkownik jest w stanie objąć wzrokiem dość pokaźną grupę miniaturek.

Jestem pewien także tego, że nieraz udało Ci się zaobserwować największy mankament miniaturek - czasami w żaden sposób nie można odcyfrować, co się dzieje na obrazku. Nadal nie wiesz, czy warto go obejrzeć... W takim razie po co miniaturka - równie dobrze mógłby ją zastąpić tekstowy odnośnik, prawda?

Skoro już uświadomiliśmy sobie problem, wyznaczmy teraz cel, do którego będziemy dążyć.

Potrzebujemy obiektu zastępującego miniaturkę, który będzie wyróżniał daną grafikę i starał się zachęcić do obejrzenia oryginału, przy jednoczesnym zachowaniu czytelności. Jeśli wziąć pod uwagę całość obrazka - jest to niemożliwe, ale kto powiedział, że trzeba nam całości? Nie lepiej wyciąć interesujący fragment?

Kadrowanie wyjściem ultymatywnym?

W przeciwieństwie do tworzenia miniaturek, kadrowanie daje zazwyczaj niezmiernie lepsze efekty wizualne. Z drugiej strony, póki nie nauczymy naszych komputerów rozpoznawania piękna, to będziemy sami musieli włożyć odrobinę naszej pracy (oraz inwencji) w wycinanki.

Pamiętaj, że ukazanie części grafiki wzbudza w oglądających ciekawość, dzięki czemu nie będą się nudzić na Twojej stronie i wysoce prawdopodobne, że jeszcze kiedyś wrócą. Istnieje pewna szansa, że dobrze uchwycony fragment będzie nie tylko intrygujący dla innych, ale stanie się nawet źródłem inspiracji dla innych.

Z powyższego akapitu płynie dość ważne pytanie - co wybrać? Z poczynionych przeze mnie doświadczeń wynikły dwa sposoby. Możemy wybrać łatwo zapadający w pamięć szczegół. Ważne przy tym, aby był reprezentatywny tylko dla jednego obrazka. Jeśli naprawdę utkwi w czyjejś pamięci, to właśnie odnieśliśmy sukces.

Inną metodą jest wybieranie najbardziej reprezentatywnej części obrazka. Problem w tym, że owszem, siła przebicia samego kadru będzie większa niż w poprzednim wypadku, jednak z drugiej strony, zabraknie nam niespodzianek w oryginale. Po pewnym czasie oglądający będzie mógł się przyzwyczaić do tego i przestanie zaglądać do oryginałów.

Może się okazać, że pewne fragmenty są zbyt duże, aby je skadrować. Wtedy należy się zastanowić, czy można bezpieczenie uciąć część tego fragmentu, czy też da się go zeskalować do pożądanych rozmiarów.

Narzędzia i wykonanie

Do tej pracy doskonale nadaje się zarówno GIMP, jak i Photoshop. Okazuje się, że moje sugestie to kombinowanie jak koń pod górę. Czujni czytelnicy (dzięki!) wskazali programy IrfanView, Picasę i JPEGCrops jako znacznie szybsze rozwiązanie przy większej ilości zdjęć. Nie testowałem żadnego z tych trzech programów, ale, jak widać, wybór jest znacznie większy.

Nie staraj się jakoś niezwykle precyzyjnie podchodzić do samego wyboru kadru - ja zazwyczaj przez chwilę zastanawiam się, jaki obiekt na obrazku rzuca się w oczy, następnie kilkakrotnie zaznaczam obszar 100x100px dookoła niego i wybieram opcję przycięcia obrazu, który zapisuję następnie jako JPEG z jakością 85 (domyślną). Dzięki temu moje wycinanki mają średnie rozmiary rzędu 3KB. Nawet przyjmując połączenie telefoniczne, dziesięć miniaturek ładuje się w jakieś 5-7s, co nie jest złym wynikiem.

Dość ważnym elementem jest wybranie stałego rozmiaru naszego kadru - dzięki temu wszystkie obrazki będą ładnie poukładane w rzędach i kolumnach na naszej stronie, niezależnie od tego, w jaki sposób zapiszemy je w kodzie HTML.

W razie, gdy obiekt, który chcesz zaznaczyć nie mieści się w domyślnych rozmiarach, można zeskalować obraz do 50% (co nadal daje w miarę dobre efekty wizualne), a następnie wykadrować i obciąć niepotrzebne części.

HTML

Gdy już zrobisz swoje miniatury i udostępnisz sieci, możesz wstawić je do swojego dokumentu. Jak? Rozwiązań jest naprawdę wiele. Można skorzystać z najprostszego kontenera <div />, lub bardziej skomplikowanej listy nieuporządkowanej.

Na tym blogu używam jeszcze innego rozwiązania. Korzystam z listy definicji <dl />, gdzie każdy <dt /> odpowiada danemu obrazkowi, a pod taką grupą wstawiam wspólny <dd />, czyli opis powyższych obiektów. Wygląda to tak:

<dl>
	<dt><img ... /></dt>
	<dt><img ... /></dt>
	[...]
	<dd>Obrazki przedstawiają x, y oraz z.</dd>
</dl>

W połączeniu z lekką stylizacją w CSS, może to wyglądać tak, jak na moim blogu.

Czy w takim razie odrobinka pracy popłaca? Odpowiedź pozostawiam Tobie.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Kurs - podstawy SQL na bazie SQLite

SQLite Administrator w działaniu

W poprzednim wpisie udało nam się zaznaczyć, że zastosowania relacyjnych baz danych są tak szerokie, że nadają się do większości typowych zadań związanych z katalogowaniem. Dziś postaramy się dowiedzieć czegoś o SQL, języku będącym swoistym rodzajem interfejsu do naszej bazy. SQL na początku może wydawać się nieco skomplikowany, ale później okaże się, że dla możliwości oferowanych przez bazę jest on rozwiązaniem optymalnym.

Nigdy nie lubiłem uczyć się czegoś na sucho - jest to nużące i daje mało efektu. Dlatego skorzystamy z SQLite. Nie wymaga on dużej ilości konfiguracji, jak inne bazy danych, wystarczy jedynie ściągnąć odpowiedni program i uruchomić go. Z tych darmowych udało mi się znaleźć jeden, bardzo przyjemny w użytku. Nazywa się SQLite Administrator, jednak ma jeden mankament - na stronie projektu jest napisane, że działa on tylko na systemach Windows 2000, XP i 2003, dzięki czemu Windowsy 9x odpadają... Dla osób, które korzystają z nich istnieje alternatywa - SQLite Database Browser, który już znacznie mniej mi się podoba, głównie dzięki temu, że jego graficzny interfejs użytkownika nie uczy dobrych nawyków. Do korzystania z konsoli jednak się nada. A więc do boju! Zainstalujmy jeden z tych programów i przejdźmy wreszcie do konkretów.

Aby nie było niejednoznaczności, wszelkie opisy działań zamieszczone dalej dotyczyć będą sqliteadmin. Osoby korzystające z innych programów będą musiały wykazać się inicjatywą i same poszukać odpowiednich opcji.

Uruchamiamy program i wybieramy opcję `Utwórz bazę danych'. W oknie dialogowym wybieramy typ pliku - baza sqlite3, wpisujemy nazwę i tyle! Baza danych została utworzona.

Teraz wybieramy kartę `Zapytanie SQL'. Większość naszej pracy będzie się z tym wiązać, choć program ma także tryb graficzny dla każdej ważniejszej opcji. Jednak dla nauki składni znacznie bardziej przyda nam się konsola, do której zapytania będziemy wpisywać ręcznie. Gdy już zrozumiemy istotę języka, wtedy nic nie będzie stało na przeszkodzie, aby wykorzystać tryb graficzny.

Po wpisaniu zapytania wciskamy F8 (wyjątkiem są zapytania z rodziny SELECT, które wykonujemy za pomocą klawisza F9). Czasami, podczas tworzenia i zmieniania tabel przydatne okaże się odświeżenie okienka po lewej, możemy kliknąć na nim prawym przyciskiem i wybrać opcję Odśwież.

CREATE TABLE - utwórz tabelkę.

A oto nasze pierwsze polecenie w SQL, które za chwilę dogłębniej zanalizujemy. Na tym etapie wystarczy wiedzieć, że celem jest stworzenie relacji - tabeli, w której będziemy zapisywać nasze dane. :)

CREATE TABLE person(name TEXT);

Wydaje się proste, nieprawdaż? Pierwsze dwa słowa odpowiadają za stworzenie nowej, pustej relacji. Następnie podajemy nazwę tej tabeli, a w nawiasie zdefiniujmy pola, które będzie zawierać. Pole `name' jest typu tekstowego. O typach danych w SQLite już wkrótce.

Wszystko w porządku? Nie, przecież relacja `person' powinna zawierać więcej atrybutów, niż tylko `name'! A tak się cieszyliśmy sukcesem... Coż, usuńmy naszą relację i stwórzmy nową.

DROP TABLE person;

CREATE TABLE person(name TEXT, surname TEXT);

Lepiej? Oho, wpadł mi do głowy pomysł. Nasza relacja może jeszcze zawierać wiek danej osoby. Kasowanie i pisanie od nowa raczej nie ma sensu, za dużo literek... Skorzystajmy jednak z dobrodziejstw języka SQL i zmodyfikujmy tabelkę.

ALTER TABLE person ADD age INT NOT NULL DEFAULT 0;

Teraz nasza tabela powiększyła się o nowe pole. I o ile ALTER TABLE person ADD age INT wydaje się zrozumiałe, to już NOT NULL oraz DEFAULT 0 jest czymś nowym. Te dwa dodatki określają, że nowe pole nie może być puste (NOT NULL), a domyślną wartością będzie 0, nawet, jeśli zapomnimy wpisać tam jakiejkolwiek wartości.

OK. Teraz możemy zacząć dodawać nowe krotki do naszej relacji.

INSERT, SELECT, UPDATE, DELETE

Na początku dodamy nową osobę.

INSERT INTO person VALUES('John', 'Doe', 26);

Kolejność wpisywania wartości zależy w tym przypadku od kolejności pól w tabeli. Ale nie ma się co martwić, możemy wybrać tylko te pola, które chcemy i w takiej kolejności, w jakiej nam się podoba.

INSERT INTO person(age, surname, name) VALUES(33, 'Doe', 'Alex');
INSERT INTO person(name) VALUES('Adam');

Spójrzmy na drugi przypadek. Nie wypełniliśmy wszystkich pól. Jaki to da nam efekt? Sprawdźmy:

SELECT * FROM person;

Okazuje się, że trzecia krotka posiada wartości ('Adam', NULL, 0). NULL jest pustą wartością, dodawaną do rekordu w momencie, kiedy brakuje pewnych danych podczas wpisywania. Jednak w przypadku pola `age' zdołaliśmy temu przeciwdziałać poprzez ustawienie atrybutu NOT NULL oraz zmiany wartości domyślnej na 0.

No dobrze, Adam NULL to raczej nie jest zbyt fortunny rekord. Zmodyfikujmy go.

UPDATE person SET surname = 'Lake', age = 5 WHERE rowid = 3;

Mamy tu kilka nowych rzeczy naraz. Po pierwsze UPDATE, które zmienia nam konkretne wartości w polach surname i age. Po drugie WHERE, dzięki któremu możemy wybrać tylko tą krotkę, która nas interesuje i pozostawić pozostałe w spokoju (tu wypada zaznaczyć, że UPDATE wywołane bez WHERE zmieni nam wszystkie wpisy w tabeli, co nie jest zbyt praktyczne). Po trzecie, rowid, który jest licznikiem generowanym automatycznie przez SQLite podczas tworzenia bazy danych. Taki numeryczny identyfikator jest bardzo przydatny, gdyż jest przyporządkowany tylko do jednej istniejącej krotki (a Johnów Doe mogą być setki). Najlepiej zilustruje to poniższy przykład.

SELECT name,surname,rowid FROM person;

Podobna metoda, jak podczas wpisywania danych, pozwala nam na wybieranie tylko tych pól, które nas interesują. Okazuje się, że przy każdym kolejnym wpisie licznik zwiększa się nam o jeden.

Tak naprawdę to Adam nie istniał. Tylko go sobie wymyśliłem. Usuńmy go.

DELETE FROM person WHERE rowid = 3;

Za to istnieje Ian Grisham, który ma 40 lat, a jego dane już uda Ci się samodzielnie wpisać.

Bardziej zaawansowane wybieranie danych.

WHERE już jest nam znane. Z powodzeniem możemy je zastosować również z poleceniem SELECT.

SELECT * FROM person WHERE surname = 'Doe';

Podczas przeszukiwania tekstu możemy skorzystać także z możliwości, jakie oferuje nam słowo kluczowe LIKE. Możemy wybrać tekst, w którym zawiera się dany ciąg znaków.

SELECT * FROM person WHERE surname LIKE 'Do%';

To zapytanie pozwoli nam znaleźć wszystkie ciągi znaków zaczynające się od Do. Przykładami są: Do, Doe, Dodododod, Do blah blah blah.

SELECT DISTINCT surname FROM person;

Dzięki DISTINCT mamy tylko niepowtarzające się dane. Dzięki temu, niezależnie od tego, ilu było Johnów Doe, otrzymamy tylko jeden wynik z tym imieniem i nazwiskiem.

SELECT COUNT(*) FROM person;

To zapytanie zwróci nam ilość wpisów w relacji.

SELECT * FROM person ORDER BY age;

Jeśli chcemy posortować wyniki według danego pola, w tym przypadku wieku, używamy ORDER BY.

SELECT * FROM person ORDER BY age LIMIT 1;

To zapytanie ograniczy nam liczbę wyników do jednego, dzięki czemu będziemy mogli wybrać najmłodszą osobę z naszej tabeli.

SELECT * FROM person ORDER BY age DESC LIMIT 1;

DESC i ASC (descending, ascending), dają nam możliwość sortowania wyniku od największego do najmniejszego lub od najmniejszego do największego. ASC jest zachowaniem domyślnym, dlatego nie musiałem go pisać w poprzednim przykładzie, choć użycie go tam jest całkowicie poprawne.

SELECT * FROM person LIMIT 1 OFFSET 2;

Zwraca jedną krotkę zaczynając po drugiej, tak więc realnie zwraca krotkę trzecią. Domyślnym zachowaniem jest OFFSET 0, którego nie musimy pisać przy zapytaniu.

SELECT surname, COUNT(*) FROM person GROUP BY surname;

Dzięki temu zapytaniu możemy sprawdzić, ile osób ma dane nazwisko...

SELECT surname,AVG(age) AS t1 FROM person GROUP BY surname ORDER BY t1;

... oraz wyliczyć średnią wieku dla danego nazwiska. Tutaj ciekawym dodatkiem jest przypisanie nowej nazwy t1 funkcji AVG(age), która odpowiada za zliczanie średniej poszczególnych wyników. Dzięki temu zamiast wpisywać nazwę funkcji po raz drugi (jako argument ORDER BY), możemy skorzystać z przypisanej nazwy. Jest to bardzo przydatna rzecz przy bardziej skomplikowanych zapytaniach, bo nie dość, że krócej się zapisuje, to potem nie będziemy musieli poprawiać kilka razy tego samego fragmentu zapytania powielonego w różnych miejscach.

Zakończenie.

Uff, udało nam się dobrnąć aż tutaj. Powyższy tekst to tak naprawdę podstawy SQLa w pigułce. Większość bardziej skomplikowanych zapytań będzie zbudowana na podstawie tych prostych form i będziemy w stanie sobie z nimi poradzić w ten, czy w inny sposób.

Powyższe przykłady z pewnymi zmianami można zastosować w każdym systemie zarządzania bazami danych. Niestety, za każdym razem będzie trzeba odkrywać na nowo te zmiany.

Do zobaczenia następnym razem. Zachowajcie tą bazę danych, przyda się nam jeszcze. :)

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Ext2/Ext3 na Windows

Mój komputer i linuksowe partycje

Jeśli ktoś przespał, zapomniał, czy też nie uświadamia sobie w ogóle takiej możliwości, przypominam - pod Windowsem NT i jego pochodnymi można używać partycji ext2/ext3 i to nie gorzej, niż FAT32. Pełny zapis/odczyt, obliczanie ilości zajętego miejsca, tworzenie, przesuwanie i usuwanie plików zapewnione.

Warto także wiedzieć, że literki podmontowanych partycji można zmieniać, wybierając opcję `IFS Drives' w Panelu Sterowania.

Strona projektu.

Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane

Hello Database

Informacje płyną w coraz szybszym tempie. Przypomina to nieco skutki globalnego ocieplenia - w pewnym momencie informacje zatopią większość ludzi. Mimo to, usilnie próbujemy powoli i nieustannie strukturalizować otaczające nas informacje. Bez szufladek, do których moglibyśmy wrzucać nowe dane, nie moglibyśmy przetrwać. Doprowadzanie danej informacji do stanu użyteczności zabierałoby tak wiele czasu, że musielibyśmy skrajnie obcinać docierające do nas sygnały.

Wiadomo, ze słów `chaos' i `porządek', cieplej zareagujemy na to drugie. Jest bardziej przewidywalne, a skoro tak, to nie ma się czego bać, bo i tak nie znajdziemy tam niczego nieznanego. Między innymi dlatego staramy się prócz strukturalizacji własnych systemów pojęciowych układać wszystko to, co się dookoła nas znajduje. Tu mała uwaga - tak zwany bałagan też jest swoistym porządkiem. Osoba, która tworzy bałagan za wygodniejsze uznaje zapamiętywanie, w którym miejscu odłożyła dany przedmiot, niż odkładanie go na jedno, to samo miejsce. Z tej strony uporządkowanie zaczyna być bardziej widoczne. ;)

Ta sama idea przyświeca komputerom - dane, jakie na nich przechowujemy są w jakiś sposób poukładane. Pliki leżą w katalogach, katalogi w innych katalogach, komputer na biurku, pani Basia na posadzce... W każdym razie idea plików jest wygodna, póki nagle nie każą nam zmienić zmienić numeru identyfikacji klienta (ang. Client Identification Number) na numer o jeden wyższy ze względu na pomyłkę działu sprzedaży (ang. Sales Management) w ostatnich dziewięćdziesięciu tysiącach plików (ang. Last 90 000 Files). Może pan Zbigniew z komputerowego by coś poradził, ale jest na chorobowym po czterech miesiącach zapalenia płuc. Oczywiście, praca musi być wykonana na wczoraj.

Dla uproszczenia zarządzania większymi ilościami powtarzalnych danych i zapobieżenia błędom podobnym do powyższego, skorzystać można z relacyjnej bazy danych. Przykładowo, wspomnianemu numerowi identyfikacji klienta można w bazie danych nadać atrybut autoinkrementacji, dzięki czemu maszyna sama zatroszczy się o dodawanie unikatowego numeru każdemu nowemu klientowi.

Dlaczego relacyjna?

Ponieważ pojęcie `bazy danych' jest tak ogólne, jak ogólne są informacje. Wszędzie tam, gdzie segregujemy dane w jakiś sposób, możliwe będzie użycie terminu `baza danych', począwszy na głowie, przechodząc przez różnego rodzaju kartoteki, kończąc wreszcie na dowolnym komputerowym systemie plików.

Ze względów historycznych, których opisanie zajęłoby dużo miejsca, pojęcie `bazy danych' zostało ograniczone do wąskiej grupy oprogramowania zwanego relacyjnymi bazami danych. Są to dość rozbudowane systemy przechowywania danych, i aby obrazowo przedstawić zasadę ich działania, zaczniemy od środka, czyli od samych danych.

W naszej bazie dane składowane są w tablicowych strukturach - relacjach 1, w jednym lub wielu plikach, zależnie od implementacji . Pomiędzy strukturami mogą występować związki mówiące o tym, że pewien rodzaj danych z jednej tabeli odnosi się do danych z drugiej tabeli. Dla przykładu pierwszym rodzajem danych był klient, a drugim produkt. Produkt był kupowany przez klienta, a więc związek jest tu jak najbardziej wskazany.

Łatwo się domyślić, że sterowanie danymi zapisanymi w tabelach i dodatkowo powiązanymi różnymi związkami nie będzie zbyt proste. To prawda - całością procesu zajmują się systemy zarządzania relacyjną bazą danych, czyli RDBMS, które są rozbudowanymi programami zajmującymi się odczytem i zapisem danych na żądanie użytkowników. Dla obsługi tych żądań został wymyślony język strukturalny język zapytań, w skrócie SQL, dzięki któremu korzystanie z możliwości oferowanych przez bazę danych staje się w miarę proste.

Zazwyczaj RDBMS jest interfejsem dla różnego rodzaju aplikacji klienckich, które wykorzystują dane w sposób adekwatny do zastosowań (prezentacja danych użytkownikowi końcowemu, drukowanie partii towaru na danym produkcie, czy też przekazywanie danych w formie raportu gdzieś dalej). Dużą zaletą dla takiego systemu może być to, że RDBMS może znajdować się na jednym komputerze w sieci, a aplikacje klienckie na innych, w tym wypadku żądania i dane będą przekazywane poprzez sieć, a na dodatek mamy pewność, że dane nie będą rozbieżne na różnych stanowiskach (że nie sprzedamy dwa razy tego samego produktu).

Sytuacja, gdzie klient, serwer przetwarzający dane i składowanie danych są od siebie odrębne, została nazwana architektura trójwarstwową. Spotyka się ją w większości baz danych, np. MySQL, PostgreSQL, Oracle, czy Microsoft SQL Server.

Co można z tym zrobić?

Zastosowania relacyjnej bazy danych są różne. I różniste.

  • Najczęściej przychodzącym do głowy wykorzystaniem może być strona internetowa, forum, wiki, blog, czy portal. Języki skryptowe, takie jak PHP, Perl, czy Python mają łatwy do użycia zestaw funkcji odpowiadających za współpracę z RDBMS. W tym wypadku wykorzystanie bazy do przechowywania artykułów, postów, czy innego rodzaju danych samo nasuwa się na myśl.
  • Większym i bardziej ambitnym przedsięwzięciem jest stworzenie systemu bazodanowego dla dowolnej firmy. W bazie możemy składować informacje o klientach, transakcjach, wpływach i wydatkach i tak dalej. Dane te wykorzystamy dla pracowników firmy, którzy będą mogli kontrolować bieżące operacje czy opracowywać zestawienia kosztów. Nic nie stoi na przeszkodzie, aby RDBMS kontrolowało także dane odpowiadające za stronę, czy też sklep internetowy firmy.
  • Ryzyko rośnie, gdy w grę wchodzą coraz większe sumy. Ale i banki korzystają z baz danych - problem w tym, że jeśli ktoś się pomyli przy projektowaniu, to ktoś inny straci, być może miliony...
  • Teraz coś z zupełnie innej beczki: SQLite jest miniaturowym systemem zarządzania bazą danych. Nie nadaje się do zastosowań, gdzie wielu użytkowników w jednej chwili potrzebuje dostępu do bazy danych, ani nie jest przystosowany do komunikacji poprzez sieć. Za to całość kodu odpowiedzialnego za przetwarzanie danych znajduje się w bibliotece, która ma blisko 250kB, przez co SQLite znakomicie nadaje się do samodzielnych aplikacji, takich jak komunikatory internetowe, czy odtwarzacze mp3. Dane przechowywane są w jednym pliku, który można łatwo wysłać mailem, czy przekopiować w inne miejsce.

Gdzie w takim razie stosować bazę danych? Wszędzie tam, gdzie użycie innych rodzajów katalogowania staje się powolne i uciążliwe.

  1. Często wspomniana tablicowość ma niewiele wspólnego z rzeczywistym zapisem na dysku, gdyż oprogramowanie sterujące wykorzystuje różne sztuczki, aby zmaksymalizować szybkość przeszukiwania. ^
Zobacz komentarze Trackback dodajdo.com Zobacz pełne metadane
Na górę
Reklamy Google