Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: SELECT COUNT, 2x WHERE?
Forum PHP.pl > Forum > Bazy danych > MySQL
fiszol
Mam dwa zapytania:
  1. SELECT COUNT(1) AS loot FROM tblname WHERE uid = xx AND item_id != 0;
  2. SELECT COUNT(1) AS spent FROM tblname WHERE uid = xx AND item_id = 0 AND mod_value < 0

Da się wyjąć te county w jednym zapytaniu?
widmo_91
UNION

  1. (SELECT COUNT(1) AS loot FROM tblname WHERE uid = xx AND item_id != 0)
  2. UNION
  3. (SELECT COUNT(1) AS spent FROM tblname WHERE uid = xx AND item_id = 0 AND mod_value < 0)
fiszol
Dzięki, to już coś, ale wynik zapytania jest inny niż oczekuje, wygląda tak:
Kod
loot
5
7


Wynik jakiego potrzebuję to:
Kod
loot    spent
5        7


Jak to osiągnąć?


//edzia. Wygooglowałem na stacku:
  1. SELECT
  2. (SELECT COUNT(1) FROM tblname WHERE uid = xx AND item_id != 0) AS loot,
  3. (SELECT COUNT(1) FROM tblname WHERE uid = xx AND item_id = 0 AND mod_value < 0) AS spent
mmmmmmm
To jest zabójstwo dla serwera. Zwłaszcza dla "rewelacyjnej" bazy, jaką jest MySQL.
Duuuuuuuuużo lepiej jest zrobić to tak:
  1. SELECT Count(CASE WHEN item_id<>0 THEN item_id END) AS loot, Count(CASE WHEN item_id=0 AND mod_value<0 THEN item_id END) AS spent FROM tblname WHERE uid=xx
fiszol
Wsadziłem w pętle, usiadłem ze stoperem i:
Kod
SELECT
    (SELECT COUNT(1) FROM smf_mpc_dkplog
    WHERE real_name = 'Rhage' AND item_id != 0) AS items,
    (SELECT COUNT(1) FROM smf_mpc_dkplog
    WHERE mod_value < 0 AND item_id = 0 AND real_name = 'Rhage') AS spent

launch #1:    0.04595 sec.
launch #2:    0.04603 sec.
launch #3:    0.04557 sec.
launch #4:    0.04691 sec.
launch #5:    0.04758 sec.
launch #6:    0.04713 sec.
launch #7:    0.04742 sec.
launch #8:    0.04653 sec.
launch #9:    0.04657 sec.
launch #10:    0.04807 sec.
total:        0.46775 sec.


SELECT COUNT(CASE WHEN item_id != 0 THEN item_id END) AS loot,
    COUNT(CASE WHEN item_id = 0 AND mod_value < 0 THEN item_id END) AS spent
    FROM smf_mpc_dkplog WHERE real_name = 'Rhage'

launch #1:    0.04780 sec.
launch #2:    0.04636 sec.
launch #3:    0.04799 sec.
launch #4:    0.04681 sec.
launch #5:    0.04723 sec.
launch #6:    0.04555 sec.
launch #7:    0.04630 sec.
launch #8:    0.04750 sec.
launch #9:    0.04891 sec.
launch #10:    0.04553 sec.
total:        0.46997 sec.

Jak na moje oko, drugie zapytanie jest ciut wolniejsze. Różnica zresztą jest taka, że ktoś musiałby mieć atomowe poczucie czasu, żeby to odczuć. Puszczałem po 1000 zapytań w 10 rzutach. Podczas normalnego użytkowania skrypt będzie wykonwał jedno zapytanie na jedno odwołanie strony. Samych odwołań nie będzie dużo (40-paru użytkowników).
mmmmmmm
Stoperem w pętli to ty se możesz mierzyć... Widać, że nie masz pojęcia jak działają bazy danych...
Ale skoro nie wierzysz mi, że jest wolniejsze, to cóż, twoja sprawa...
fiszol
Nie powiedziałem, że nie wierzę. Zmierzyłem, jak potrafię. Teraz jeszcze podglądłem sobie obciążenie na procesorze, drugie zapytanie w szczytowym momencie ~2-3% mniej. Biorąc pod uwagę "skalę projektu" i mozlwiości dzisiejszych serwerów, różnice zarówno w czasie i obciązeniu są śmieszne, nie istotne w tym konkretnym przypadku.
Doldox
Witam serdecznie,
posiadam problem, z którym niestety nie poradziłem sobie sam. Z internetu tak jak Kolega Fiszol wygooglowałem połowiczne rozwiązanie prezentacji zapytania jakie mnie interesuje.

W sumie to rozwiązań mojego problemu może być dwa, ale od poczatku.

Opcja rozwiązania nr1:

Moje zapytanie SQL to:
  1. SELECT
  2. (
  3. SELECT count(`Wynik`)
  4. FROM `Historia2`
  5. WHERE `Wynik`="Zdany"
  6. ) AS Zdanych,
  7. (
  8. SELECT count(`Wynik`)
  9. FROM `Historia2`
  10. WHERE `Wynik`="Oblany"
  11. ) AS Oblanych

Które jest oczywiście podobne do Kolegi Fiszol'a.
Wynikiem zapytania jest:
Kod
Zdanych Oblanych
6     2

Problem w tym, że chciałbym mieć informacje z podziałem na nazwiska ludzi biorących udział w testach.
Czyli np:
Kod
Człek    Zdanych    Oblanych
Kowalski    3    0
Nowak    0    1
Iksiński    3    1

Tego niestety nie potrafię zrobić. Wynik jaki dostaje po swoich kombinacjach to:
Kod
Człek    Zdanych    Oblanych
Kowalski    6    2
Nowak    6    2
Iksiński    6    2

a zapytanie to:
  1. SELECT Pracownik,
  2. (
  3. SELECT count(`Wynik`)
  4. FROM `Historia2`
  5. WHERE `Wynik`="Zdany"
  6. ) AS Zdanych,
  7. (
  8. SELECT count(`Wynik`)
  9. FROM `Historia2`
  10. WHERE `Wynik`="Oblany"
  11. ) AS Oblanych
  12. FROM `Historia2`
  13. GROUP BY `Historia2`

Opcja rozwiązania nr2:
Skoro posiadam liczbę testów danego człowieka, wystarczy, że wyciągnę ilość albo zdanych albo oblanych i odejmę ją od całości, w ten sposób w PHP już sobie spokojnie policze, ale problem jest taki, że nie wyświtla mi wartości zerowej. Czyli korzystając z kodu:
  1. SELECT count(`Wynik`)
  2. FROM `Historia2`
  3. WHERE `Wynik`="Zdany"

Wyświetli mi tylko dwóch Panów z przykładu powyżej - i nici z odejmowania..

Pomocy sad.gif

Pozdrawiam,
Doldox
mmmmmmm
  1. SELECT Pracownik, Count(Case When Wynik='Zdany' then Wynik end)-Count(Case When Wynik='Oblany' Then wynik end) FROM Historia2 GROUP BY 1

Doldox
W sumie nie wiem dlaczego odejmowane są te wartości od siebie, ale zamieniłem znak "-" na "," i wyświetla mi dokładnie to co chciałem w opcji nr 1 z mojego porzedniego posta co prowadzi mnie to rozwiązania problemu, dziękuję bardzo! Piwo dla Ciebie!

  1. SELECT Pracownik, Count(Case When Wynik='Zdany' then Wynik end), Count(Case When Wynik='Oblany' Then wynik end) FROM Historia2 GROUP BY 1


Dzięki temu powyżej mogę teraz użyc obu opcji rozwiązania w zależności od potrzeby. I na przyszło oczywiście przyjrze się opcji Case when smile.gif

Pozdrawiam,
Doldox
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-2024 Invision Power Services, Inc.