Avatar billede staalaben Nybegynder
03. november 2005 - 16:37 Der er 7 kommentarer og
1 løsning

Medarbejdere ansat pr. år?

Hej,

Jeg har et spørgsmål!

Jeg har en liste med personer - de har hver en startDato og slutDato for deres ansættelse/tilmelding.

Jeg skal lave en liste der fortæller hvor mange personer der har været hvert år siden den første person blev ansat til den sidste er stoppet.

Der er ikke nødvendigvis ansat eller stoppet nogle personer hvert år men alle år i intervallet skal være med i listen.

Der må kun bruges Oracle SQL - ikke noget front end sjov ;o)

Jeg ved ikke om spørgsmålet er let eller svært - jeg gir' max point anyway!
Avatar billede kjulius Novice
03. november 2005 - 22:28 #1
Jeg kender ikke noget til Oracle, men da det lyder som noget der er temmelig standard SQL, vil jeg da gerne gøre et forsøg...

Start med at oprette en tabel med årstal:

CREATE TABLE MEDARB.ÅRSTAL (ÅR DEC (4 , 0) NOT NULL WITH DEFAULT)

Fyld så nogle data i tabellen:

INSERT INTO MEDARB.ÅRSTAL VALUES(1995)
INSERT INTO MEDARB.ÅRSTAL VALUES(1996)
INSERT INTO MEDARB.ÅRSTAL VALUES(1997)
INSERT INTO MEDARB.ÅRSTAL VALUES(1998)
INSERT INTO MEDARB.ÅRSTAL VALUES(1999)
INSERT INTO MEDARB.ÅRSTAL VALUES(2000)
INSERT INTO MEDARB.ÅRSTAL VALUES(2001)
INSERT INTO MEDARB.ÅRSTAL VALUES(2002)
INSERT INTO MEDARB.ÅRSTAL VALUES(2003)
INSERT INTO MEDARB.ÅRSTAL VALUES(2004)
INSERT INTO MEDARB.ÅRSTAL VALUES(2005)
INSERT INTO MEDARB.ÅRSTAL VALUES(2006)
INSERT INTO MEDARB.ÅRSTAL VALUES(2007)
INSERT INTO MEDARB.ÅRSTAL VALUES(2008)
INSERT INTO MEDARB.ÅRSTAL VALUES(2009)
INSERT INTO MEDARB.ÅRSTAL VALUES(2010)

Nu er du så klar til at forsøge dig med en forespørgsel:

SELECT ÅRSTAL.ÅR, SUM(CASE WHEN YEAR(MEDARB.STARTDATO) <= ÅRSTAL.ÅR AND (MEDARB.STOPDATO IS NULL OR YEAR(MEDARB.STOPDATO) >= ÅRSTAL.ÅR)THEN 1 ELSE 0 END) AS ANSATTE
FROM MEDARB.ÅRSTAL, MEDARB.MEDARBEJDERE AS MEDARB
WHERE ÅRSTAL.ÅR <= YEAR(CURDATE())                                               
GROUP BY ÅRSTAL.ÅR
ORDER BY ÅRSTAL.ÅR

Eller alternativt kan man bruge en lidt anden syntax:

SELECT ÅRSTAL.ÅR, SUM(CASE WHEN YEAR(MEDARB.STARTDATO) <= ÅRSTAL.ÅR AND (MEDARB.STOPDATO IS NULL OR YEAR(MEDARB.STOPDATO) >= ÅRSTAL.ÅR)THEN 1 ELSE 0 END) AS ANSATTE
FROM MEDARB.ÅRSTAL
CROSS JOIN MEDARB.MEDARBEJDERE AS MEDARB
WHERE ÅRSTAL.ÅR <= YEAR(CURDATE())                                               
GROUP BY ÅRSTAL.ÅR
ORDER BY ÅRSTAL.ÅR

Som sagt, så tror jeg også den vil virke på en Oracle database, da der er ikke er brugt specielle funktioner. Prøv den... :-)
Avatar billede kjulius Novice
03. november 2005 - 22:40 #2
Jeg har lige genlæst spørgsmålet, og er kommet lidt i tvivl om, hvorvidt jeg har misforstået det lidt. Derfor lige en tilføjelse:

SELECT ÅRSTAL.ÅR, SUM(CASE WHEN YEAR(MEDARB.STARTDATO) <= ÅRSTAL.ÅR AND (MEDARB.STOPDATO IS NULL OR YEAR(MEDARB.STOPDATO) >= ÅRSTAL.ÅR)THEN 1 ELSE 0 END) AS ANSATTE, SUM(CASE WHEN YEAR(MEDARB.STARTDATO) = ÅRSTAL.ÅR THEN 1 ELSE 0 END) AS NYANSATTE, SUM(CASE WHEN YEAR(MEDARB.STOPDATO) = ÅRSTAL.ÅR THEN 1 ELSE 0 END) AS STOPPEDEANSATTE 
FROM MEDARB.ÅRSTAL
CROSS JOIN MEDARB.MEDARBEJDERE AS MEDARB
WHERE ÅRSTAL.ÅR <= YEAR(CURDATE())                                               
GROUP BY ÅRSTAL.ÅR
ORDER BY ÅRSTAL.ÅR

Princippet er det samme. Der er bare tilføjet en optælling af, hvor mange der er hhv. startede og stoppede i årets løb.
Avatar billede staalaben Nybegynder
03. november 2005 - 23:07 #3
Mit problem er, at jeg ikke har en tabel med årstal og egentligt ikke har beføjelser til at oprette sådan (skole projekt).

Jeg har 1 tabel der skal bruges:

medarbejdere (navn, startDato, slutDato)

Ikke mere...

Jeg har lavet lidt kode, hvor den beregner hvor mange ansatte der er hvert år, hvor der sker et skift i antallet - at en ny bliver ansat eller en gammel stopper. Men de år, hvor antallet er uændret bliver ikke repræsenteret... Tror min løsning er acceptabel men det kunne være rart med alle år i listen!

Håber det var mere klart :o)

/ Aben
Avatar billede kjulius Novice
04. november 2005 - 09:08 #4
Okay, ja det er jo lidt af et problem :-)

Jeg ved ikke om Oracle databasen har en funktion, som kan generere årstallene uden en egentlig tabel. Dertil kender jeg som sagt for lidt til denne database, men det er da ikke helt umuligt. Oracle er jo kendt for at have mange funktioner uden for standarderne. Jeg har ikke selv adgang til manualerne (de ligger ikke frit tilgængelige på Oracles site, som de gør på de fleste andre databaseproducenters), så jeg kan ikke umiddelbart komme på noget. Medmindre du kan "låne" fra en anden tabel, som du ved indeholder et numerisk felt med en ubrudt række af fortløbende tal. Så kan du jo trække på den i stedet og lægge til og trække fra, indtil du får den serie af årstal du ønsker. Ikke det mest elegante, men måske virker det jo for dig?...
Avatar billede arne_v Ekspert
06. november 2005 - 20:09 #5
test data:

CREATE TABLE employees (
    id INTEGER PRIMARY KEY,
    name VARCHAR2(50),
    startdate DATE,
    enddate DATE
);

INSERT INTO employees VALUES (1, 'Anders Andersen', '20020201', '20051031');
INSERT INTO employees VALUES (2, 'Børge Børgesen', '20040101', '20051031');
INSERT INTO employees VALUES (3, 'Christian Christensen', '20050101', '20051031');

query:

SELECT x.y,COUNT(*)
FROM employees,(SELECT (SELECT MIN(TO_CHAR(startdate,'YYYY')) FROM employees)+ROWNUM-1 AS y
                FROM ALL_USERS,ALL_USERS
                WHERE ROWNUM <= (SELECT MAX(TO_CHAR(enddate,'YYYY'))-MIN(TO_CHAR(startdate,'YYYY'))+1 FROM employees)) x
WHERE TO_CHAR(employees.startdate,'YYYY') <= x.y AND x.y <= TO_CHAR(employees.enddate,'YYYY')
GROUP BY x.y;

output:


        Y  COUNT(*)
---------- ----------
      2002          1
      2003          1
      2004          2
      2005          3

hvilket ser rigtigt ud !
Avatar billede arne_v Ekspert
06. november 2005 - 20:10 #6
jeg har tilladt mig at antage at:

antal brugere i databasen * antal brugere i databasen >= antal år vi skal dække

men hvis det er for lidt så find en anden stor tabel
Avatar billede arne_v Ekspert
20. november 2005 - 19:59 #7
staalabe ?
Avatar billede arne_v Ekspert
31. december 2005 - 15:09 #8
Tid at få afsluttet her ?

og et svar fra mig
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