Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Sortowanie liczb ujemnych w MySQL
Largo
post
Post #1





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 13)
skowron-line
post
Post #2





Grupa: Zarejestrowani
Postów: 4 340
Pomógł: 542
Dołączył: 15.01.2006
Skąd: Olsztyn/Warszawa

Ostrzeżenie: (0%)
-----


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.


--------------------
I'm so fast that last night I turned off the light switch in my hotel room and was in bed before the room was dark - Muhammad Ali.
Peg jeżeli chcesz uprawiać sex to dzieci muszą wyjść, a jeżeli chcesz żeby był dobry ty też musisz wyjść - Al Bundy.

QueryBuilder, Mootools.net, bbcradio1::MistaJam
http://www.phpbench.com/
Go to the top of the page
+Quote Post
phpion
post
Post #3





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




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.
Go to the top of the page
+Quote Post
Largo
post
Post #4





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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?
Go to the top of the page
+Quote Post
Ges
post
Post #5





Grupa: Zarejestrowani
Postów: 61
Pomógł: 9
Dołączył: 22.02.2008

Ostrzeżenie: (0%)
-----


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 :]
Go to the top of the page
+Quote Post
maly_swd
post
Post #6





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

Ostrzeżenie: (0%)
-----


a takie cos? pisane na szybko:
  1. SELECT IF(value<0, -1,1 ) AS znak, value
  2. FROM test ORDER BY znak, value DESC


Ten post edytował maly_swd 18.11.2009, 11:43:43


--------------------
śmieszne obrazki
Kryzys: Ser jem spleśniały, wino piję stare i samochód mam bez dachu..
Go to the top of the page
+Quote Post
Largo
post
Post #7





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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!

Ten post edytował Largo 18.11.2009, 12:05:54
Go to the top of the page
+Quote Post
Ges
post
Post #8





Grupa: Zarejestrowani
Postów: 61
Pomógł: 9
Dołączył: 22.02.2008

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Largo
post
Post #9





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
Ges
post
Post #10





Grupa: Zarejestrowani
Postów: 61
Pomógł: 9
Dołączył: 22.02.2008

Ostrzeżenie: (0%)
-----


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 ?
Go to the top of the page
+Quote Post
Largo
post
Post #11





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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

Ten post edytował Largo 18.11.2009, 15:55:34
Go to the top of the page
+Quote Post
Ges
post
Post #12





Grupa: Zarejestrowani
Postów: 61
Pomógł: 9
Dołączył: 22.02.2008

Ostrzeżenie: (0%)
-----


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 :]
Go to the top of the page
+Quote Post
Largo
post
Post #13





Grupa: Zarejestrowani
Postów: 203
Pomógł: 6
Dołączył: 11.09.2005

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
Ges
post
Post #14





Grupa: Zarejestrowani
Postów: 61
Pomógł: 9
Dołączył: 22.02.2008

Ostrzeżenie: (0%)
-----


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

Powodzenia
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 20.08.2025 - 19:38