Avatar billede kxh Nybegynder
16. juli 2004 - 13:09 Der er 13 kommentarer og
2 løsninger

SQL forespørgsel

Hej

Jeg har en tabel indeholdene følgende felter:

IPadresse
IDstatus

IDstatus kan indeholde flere forskellige værdier, normal
vil den indeholde i seks cifret tal, men hvis den ikke har læst et nummer vil der stå NOREAD.
Hvordan kan man lave en forspørgsel som giver følgede resultat

IPadresse:  AntalLæst:  AntalIkkeLæst:

Med venlig hilsen

Kim Hansen
Avatar billede dmk Nybegynder
16. juli 2004 - 13:27 #1
Jeg er ikke sikker på jeg helt forstår opgaven, men måske sådan her:

select a.IPAdresse, AntalLaest, AntalIkkeLaest
from
(
  select IPAdreesse, count(*) as AntalIkkeLaest
  from MyTable
  where IDStatus='NOREAD'
  group by IPAdresse
) a,
(
  select IPAdreesse, count(*) as AntalIkkeLaest
  from MyTable
  where IDStatus!='NOREAD'
  group by IPAdresse
) b
where a.IPAdresse=b.IPAdresse;


/DMK
Avatar billede kibeha Nybegynder
16. juli 2004 - 13:27 #2
Du kan udnytte at count(<noget>) kun tæller ikke-null værdier :

select
  ipadresse,
  count(case when idstatus = 'NOREAD' then null else 1 end) antallaest,
  count(case when idstatus = 'NOREAD' then 1 else null end) antalikkelaest
from tabel
group by ipadresse


mvh. en anden Kim Hansen ;-)
Avatar billede dmk Nybegynder
16. juli 2004 - 13:28 #3
Whoups, cut&paste fejl. I Sub-select 2 skal count-feltet naturligvis hedde AntalLaest...

/DMK
Avatar billede janus_007 Nybegynder
16. juli 2004 - 13:31 #4
Det er ikke så elegante løsninger, jeg vil nok foreslå at gøre sådan her:

select IPadresse, sum(isnumeric(IDstatus)) as AntalLæst, count(*) - sum(isnumeric(IDstatus)) as AntalIkkeLæst from table
group by IPadresse


;O)
Avatar billede kxh Nybegynder
16. juli 2004 - 13:35 #5
Hejsa

Tak for alt din hjælp, det var godt nok hurtigt, jeg har valgt den sidste udgave

// Kim Hansen
Avatar billede kibeha Nybegynder
16. juli 2004 - 13:36 #6
Så kan janus' og min løsning kombineres :

select
  ipadresse,
  count(case when isnumeric(idstatus) then 1 else null end) antallaest,
  count(case when isnumeric(idstatus) then null else 1 end) antalikkelaest
from tabel
group by ipadresse


På den måde slipper man også for afhængigheden af det "hard-codede" NOREAD.

Du har altså mange muligheder :-)
Avatar billede kxh Nybegynder
16. juli 2004 - 13:37 #7
Kan man trylle videre, ved at den automatisk kan beregne procenten... altså
procenten af hvor mange tags der er blevet læst ialt...
Avatar billede kibeha Nybegynder
16. juli 2004 - 13:56 #8
F.eks. :

select
  ipadresse,
  antallaest,
  antalikkelaest,
  case
    when antallaest+antalikkelaest > 0 then
      100*antallaest/(antallaest+antalikkelaest)
    else
      0
  end pctlaest,
  case
    when antallaest+antalikkelaest > 0 then
      100*antalikkelaest/(antallaest+antalikkelaest)
    else
      0
  end pctikkelaest
from (
  select
    ipadresse,
    count(case when isnumeric(idstatus) then 1 else null end) antallaest,
    count(case when isnumeric(idstatus) then null else 1 end) antalikkelaest
  from tabel
  group by ipadresse
) s
Avatar billede kibeha Nybegynder
16. juli 2004 - 13:58 #9
Egentlig kunne du måske nøjes med :

select
  ipadresse,
  antallaest,
  antalikkelaest,
  100*antallaest/(antallaest+antalikkelaest) pctlaest,
  100*antalikkelaest/(antallaest+antalikkelaest) pctikkelaest
from (
  select
    ipadresse,
    count(case when isnumeric(idstatus) then 1 else null end) antallaest,
    count(case when isnumeric(idstatus) then null else 1 end) antalikkelaest
  from tabel
  group by ipadresse
) s


Årsagen til du kan nøjes med det er, at antallaest og antalikkelaest er komplementære, så du kan være sikker på, at antallaest+antalikkelaest vil altid være > 0.

Men generelt bør man huske tjekket for ikke at få "division med nul" fejl...
Avatar billede kxh Nybegynder
16. juli 2004 - 14:02 #10
Den giver en fejl

incorrect syntax near keyword 'then'
Avatar billede kibeha Nybegynder
16. juli 2004 - 14:04 #11
Og så lige et yderligere raffinement :-)

select
  ipadresse,
  antallaest,
  antalikkelaest,
  100*antallaest/(antallaest+antalikkelaest) pctlaest,
  100*antalikkelaest/(antallaest+antalikkelaest) pctikkelaest
from (
  select
    ipadresse,
    count(nullif(isnumeric(idstatus),1)) antallaest,
    count(nullif(isnumeric(idstatus),0)) antalikkelaest
  from tabel
  group by ipadresse
) s


Jeg havde lige glemt nullif(), som netop er en specialiseret case til dette formål...
Avatar billede kibeha Nybegynder
16. juli 2004 - 14:05 #12
Syntax fejlen er nok min fejl. Dette skulle virke :

select
  ipadresse,
  antallaest,
  antalikkelaest,
  100*antallaest/(antallaest+antalikkelaest) pctlaest,
  100*antalikkelaest/(antallaest+antalikkelaest) pctikkelaest
from (
  select
    ipadresse,
    count(case when isnumeric(idstatus)=1 then 1 else null end) antallaest,
    count(case when isnumeric(idstatus)=1 then null else 1 end) antalikkelaest
  from tabel
  group by ipadresse
) s

Men endnu bedre er nullif() konstruktionen i foregående kommentar.
Avatar billede janus_007 Nybegynder
16. juli 2004 - 14:19 #13
Det trylleri hører til i en ny tråd ;O)


Men jeg må nok virkelig fraråde alle de besynderlige statements med cases og subselects osv. De performer virkelig dårligt når der er mange rækker i tabellen.
Avatar billede kibeha Nybegynder
16. juli 2004 - 14:25 #14
Kommentar til janus' kommentar :

Jeg ændrede også brugen af case til nullif() :-)

Og hvad angår performance kan jeg da sige jeg benytter både case og subselects og mange andre konstruktioner i store sql-statements med mange joins og på tabeller med mange rækker i vores 300GB Oracle database - og det performer *rigtig* godt...

Det er muligt det ikke performer helt så godt i MS SQL - den har jeg knap så stor erfaring med. Jeg har mest brugt MS SQL til mindre baser. Så hvis du siger det ikke performer i MS SQL, så skal jeg ikke modsige dig (alt for meget i hvert fald :-)

Så der kan jeg kun anbefale kxh at afprøve tingene og se hvorvidt de performer...
Avatar billede kxh Nybegynder
16. juli 2004 - 15:13 #15
Hejsa

Der er en lille detalje, som nogen brugere måske vil hænge sig i, kan man få procenten vis med decimaler, da den f.eks lige nu skrive 91 og 8 hvor er den sidste, vil de sikkert spørge ??

// Kim
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester