Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sortowanie liczb ujemnych w MySQL
Forum PHP.pl > Forum > PHP
Largo
Witam,

Oto schemat bazy danych na dobry początek:

  1. CREATE TABLE ibf_fg_transactions
  2. (
  3. id int(10) NOT NULL AUTO_INCREMENT,
  4. sender_id int(10) DEFAULT '0',
  5. sender_fg decimal( 10, 2 ) DEFAULT '0.00',
  6. sender_ip varchar(15) DEFAULT '0.0.0.0',
  7. recipient_id int(10) DEFAULT '0',
  8. recipient_fg decimal( 10, 2 ) DEFAULT '0.00',
  9. is_system tinyint(1) NOT NULL DEFAULT '0',
  10. amount decimal( 10, 2 ) NOT NULL SIGNED DEFAULT '0.00',
  11. comment varchar(255),
  12. visible tinytint(1) NOT NULL DEFAULT '0',
  13. date int(10) NOT NULL,
  14. PRIMARY KEY( id )
  15. )


Problem leży w sortowaniu. Sortuję po dacie, po kwocie i po kim, czyli po nazwie użytkownika, a dokładnie odbiorcy, bo wysyłający to my. Po dacie i nazwie działa, ale po kwocie nie. Kwoty zapisuję zazwyczaj tylko jako dodatnie, ale postanowiłem, że systemowe będę zapisywał jako minusowe. I moje pytanie - jak stworzyć zapytanie, które będzie takie coś robiło lub jak zmienić schemat bazy danych?

Pozdrawiam,
Largo
skowron-line
Cytat(Largo @ 18.11.2009, 10:43:48 ) *
Witam,

Oto schemat bazy danych na dobry początek:

  1. CREATE TABLE ibf_fg_transactions
  2. (
  3. id int(10) NOT NULL AUTO_INCREMENT,
  4. sender_id int(10) DEFAULT '0',
  5. sender_fg decimal( 10, 2 ) DEFAULT '0.00',
  6. sender_ip varchar(15) DEFAULT '0.0.0.0',
  7. recipient_id int(10) DEFAULT '0',
  8. recipient_fg decimal( 10, 2 ) DEFAULT '0.00',
  9. is_system tinyint(1) NOT NULL DEFAULT '0',
  10. amount decimal( 10, 2 ) NOT NULL SIGNED DEFAULT '0.00',
  11. comment varchar(255),
  12. visible tinytint(1) NOT NULL DEFAULT '0',
  13. date int(10) NOT NULL,
  14. PRIMARY KEY( id )
  15. )

Ale to tylko tabela nie baza danych smile.gif no ale czepiam się
Jeżeli masz same liczby ujemne to ORDER BY ABS( liczby_ujemne ) DESC czyli odwrotne sortowanie liczb dodatnich.
phpion
Cytat(skowron-line @ 18.11.2009, 13:01:13 ) *
Ale to tylko tabela nie baza danych smile.gif no ale czepiam się

To i ja się czepię: w takim razie według Ciebie czym jest schemat bazy danych? Bo dla mnie jest to schemat tabel w niej się znajdujących, a jeśli kolega ma jedną tabelę to schemat bazy = schemat tej tabeli.

@Largo:
Wydaje mi się, że wszystko powinno działać bez żadnego kombinowania. Daj tu jeszcze zrzut jakiś przykładowych danych z tej tabeli (najlepiej w formie INSERT INTO) oraz zapytanie, którym wybierasz później dane.
Largo
Witam,

skowron-line - masz rację, pomyliłem się, ale inne tabele nie są potrzebne do tego problemu :-)

Czego problem dotyczy chłopaki? Kupując via automat, dodaję kwotę w postaci ujemnej, ale zwykłe transakcje ( user -> user ) wysyła kwoty normalne, i nie wiem czy muszę pobawić się przy tabeli, czy znacie rozwiązanie dla tego?

Np. kupiłem coś i mam -100, potem wysyła mi użytkownik 200, a ja mu odsyłam 100. Co daję wynik kwoty:

-100, 200, 100

Z tego sortowanie nie wyjdzie, bo pokażę i -100, potem 100 ( bo niższa kwota ) i 200, ale jakbyś dali 300, to ona byłaby ponad. Muszę przeprojektować tabele, czy macie inne sugestie?
Ges
Może dorzuć jeszcze do tabeli typ transakcji ? I tam będziesz mógł wrzucić -1 / 1 w zależności czy user->user czy systemowe.
Sortowałbyś po KWOTA * TYP, wtedy.

Chociaż przyznam się, że do końca nie rozumiem Twojego problemu i czemu zapisywać wogóle wydawanie pieniędzy jako dodatnie wartości.

Moim zdaniem zamiast kombinować, zmień błędne założenia :]
maly_swd
a takie cos? pisane na szybko:
  1. SELECT IF(value<0, -1,1 ) AS znak, value
  2. FROM test ORDER BY znak, value DESC
Largo
Witam,

Dlatego to właśnie napisałem! Nie wiem czy tabela nie została przekombinowana, czy dobrze to przemyśleliśmy... Czemu dawałem dodatnie kwoty? Jeden INSERT to informacje dla dwóch osób. Jedna widzi, że otrzymała z klasą CSS dodatnią itp, a inna odwrotnie. Jeżeli zapisywałbym kwotę ujemną zawsze to nie wiem czy to byłoby rozsądne?

Flaga is_system sugeruje to, że transakcja jest systemowa lub jej brak, że nie jest, co dodatkowo oznajmia brak danych nt. odbiorcy ( recipient_id = 0, recipient_fg = 0.00 ), więc ja to tak rozmyśliłem. Może błędnie, chętnie przyjmę nowe sugestie.

Oto dane dla phpion:

  1. SELECT fg.*,s.member_id AS s_id, s.members_display_name AS s_name, s.member_group_id AS s_group, s.donate_icon AS s_icon,r.member_id AS r_id, r.members_display_name AS r_name, r.member_group_id AS r_group, r.donate_icon AS r_icon,t.description FROM ibf_fg_transactions fg LEFT JOIN ibf_members s ON ( fg.sender_id=s.member_id )
  2. LEFT JOIN ibf_members r ON ( fg.recipient_id=r.member_id )
  3. LEFT JOIN ibf_fg_transactions_type t ON ( fg.type=t.type_id ) WHERE sender_id=1 OR recipient_id=1 GROUP BY id ORDER BY date DESC LIMIT 0,30


User -> User:
  1. INSERT INTO ibf_fg_transactions VALUES( 1, 100.00, '10.10.0.1', 2, 1000.00, 0, 50.00, 'Test', 0, '123456789' )


System:
  1. INSERT INTO ibf_fg_transactions VALUES( 1, 100.00, '10.10.0.1', 0, 0.00, 1, -50.00, 'Test', 0, '123456789' )


Pozdrawiam!
Ges
Radziłbym jednak przeprojektować tą bazę i inaczej zaplanować transakcje.
Ja bym zapisywał wszystko w dodatnich wartościach + typ transakcji.

Jeśli dałbyś typ:

0 - system
1 - user->user

to moglbys wtedy swobodnie sortowac w ten sposob, że najpierw po typie (0 byłyby same ujemne) (1 sam dodatnie) i w drugiej kolejności po faktycznej kwocie.

Zrezygnowałbym jeszcze z zapisywania isSystem, które nic nie wnosi do tabeli tylko duplikuje logike zapisywania ID nadawcy / odbiorcy.
Largo
Witaj,

Problem z tym, że systemowe transakcje w paru przypadkach mogą być pozytywne, tzn. użytkowników coś z tych operacji otrzymuje :-) Co wtedy? Ogólnie Twój zamysł mi się podoba i raczej skuszę się na niego. Musimy jedynie skorygować ten problem.

Pozdrawiam,
Largo
Ges
Nie do końca też rozumiem po co sortowanie po KWOCIE w tym modelu. Czy wogóle w aplikacji będziesz sortował zarówno kwoty z systemu dodatnie jak i ujemne w jednym widoku ?

Poza tym moim zdaniem sortowanie po transakcjach nie powinno uwzględniać znaku transakcji tylko jej wielkość.
Czyli miałbyś coś takiego:

300
-250
200
-100
50

Takie byłoby sortowanie a nie:

-300
-100
100
200
300

Nie do końca wiem jaki chciałbyś efekt uzyskać. Czy mógłbyś na jakmś przykładzie to puścić ?

Dajmy na to transakcje:

1. user-user (+300)
2. user-user (+100)
3. systemowa (-100)
4. systemowa (-200)
5. systemowa (+150)

Jakbyś to widzieć to po przesortowaniu ?
Largo
Witaj,

W sumie masz rację, ale cała ekipa i postanowienia zostały zmienione. Nagle nie widzą sensu do sortowania po kwocie. A czy Twój sposób:

300
-250
200
-100
50

Będzie działał na tej zasadzie co opisałeś powyżej? Usunąłem is_system, dodałem type dla tinyint(1) i jako 0 dałem zwykłe, a 1 jako systemowe. I jeżeli chciałbym sortować, wystarczy tylko tych danych używać?

Pozdrawiam,
Largo
Ges
Dla takiego efektu to nie widze wogóle problemów...

Sortujesz tylko po KWOTA DESC zapisując zawsze tylko wartości dodatnie.

Minus ("-") przed liczbami musi się pojawić tylko dla użytkownika, ale nie bierze udziału w sortowaniu. Więc tak naprawdę do samego sortowanie używajcie tylko kwot dodatnich i po tym możecie sortować uzyskując powyższy efekt.

Jeśli chodzi o znak to właśnie bazowałbym na tym polu TYP, czyli w modelu MVC w widoku sprawdzasz czy transakcja wyświetlana jest typu USER_USER czy SYSTEM_MINS bądź może SYSTEM_PLUS i wtedy to już tylko jest logika widoku czy pokazać minusa czy nie.

W bazie byloby tak:

KWOTA TYP
____________________
300 USER_USER
250 SYSTEM_MINUS
200 SYSTEM_PLUS
100 USER_USER
50 SYSTEM_MINUS

Robisz wtedy tylko "ORDER BY KWOTA DESC" i masz przesortowane tak jak chciałeś.
Podczas wyświetlania w PHPie

foreach($transactions as $trans)
{
if($trans['typ'] == SYSTEM_MINUS) print "-";
print $trans['kwota'];
}

Kod oczywiście bardziej podglądowy niż do użycia. W bazie danych TYP proponowałbym jako ENUMa zrobić a zmienne w PHP define('').
Ale szczegóły implementacji już pozostawiam Wam smile.gif

Wg mnie problem był poprostu źle wytłumaczony :]
Largo
Witaj,

Albo jeszcze inaczej... Podczas transakcji systemowych mam do wyboru zapis dodatni lub ujemny. Zawsze mogę dodać parametr do zapisu transakcji i tam określać czy zapisać log systemowy, jako dodatni lub ujemny. Zapis taki sam idzie do bazy, a w logice prosty kod:

  1. $row['amount'] = ( $this->doFormatFG( $row['amount'] ) < 0 ) ? abs( $row['amount'] ) : $row['amount'];


I mam po problemie, ale Twoje propozycję rozważę. Zobaczę co powie kolega, ale pewnie zgodzimy się z Tobą :-) Dzięki za rozwiązanie problemu, teraz już nie ma kłopotu z tym i parę innych spraw się wyjaśniło.

Pozdrawiam,
Largo
Ges
Liczy się idea smile.gif Rozwiązań jest zawsze parę. Najlepsze musi dobrać sami w szerszym kontekście projektu :]

Powodzenia
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.