Avatar billede MesterErbs Nybegynder
10. februar 2010 - 10:42 Der er 5 kommentarer og
1 løsning

Måske regular expresion till loop ad datoer

Hej

Jeg har en kalender som viser en måned af gangen. For hver dag har jeg en query der spørger om der findes nogle events på den pågældende dag. Hver event findes under tabellen "contract", men da man kan skal kunne vælge flere datoer til samme event, har jeg en relations tabel "contractdates".
"contractdates" indeholder: id, contractid, dates, md, yy
Der oprettes en record for hver md, for hver år. Dvs. at der for hver record kun kan være en md og et yy, men flere dates. Dates er opdelt med [].
Jeg har flg. query for hver dato i min kalender:

SELECT `user`.`fornavn`, `user`.`efternavn`, `groups`.`navn`, `contract`.*, `contractdates`.*
  FROM `contract`
LEFT JOIN `contractdates`
  ON `contractdates`.`contractid` = `contract`.`id`  
LEFT JOIN `groups`
  ON  `groups`.`id` = `contract`.`groupid`
LEFT JOIN `user`
  ON `user`.`id` = `contract`.`userid`
WHERE `contractdates`.`dates`
  LIKE '[%wdays%]'
AND `contractdates`.`md`
  LIKE '%this_month%'
AND `contractdates`.`yy`
  LIKE '%this_year%'

Problemet er at den ikke vil vise eventet hvis der er flere end en dato!
Skal jeg have en query uden om med contractdates eller skal jeg ud i noget regular expression?
10. februar 2010 - 22:14 #1
mestererbs, du siger at i tabellen contractdates kan hver rekord have flere dates.  Mener du, for eksempel, saaledes:
contraktdates
id contractid date date date md yy
1  1          25  26  26  01 2010

Jamen saa ligger problemet her, strukturen i tabellen er forkert (egner sig ikke til SQL queries.)

Jeg er enig med din struktur i user, groups, og contrakt hvor der er en mange-til-mange relation mellem users o og groups og det fastlaegger du i tabellen contract ved at lade contract relatere til (have fremmednoegle til) baade user og groups.  Saa er der en En-til-mange relation mellem contract og contractdates, en contract kan have mange dates, hvilket du fastlaegger ved at lade contractdates have fremmednoegle til contracts.  Det simpleste er saa lade contractdates have tre felter, en id, en contractid og en fuld dato med dag, maaned, og aar.  Hvis contrakt nummer 25 kan finde sted 1 januar 2010 og 2 januar 2010 og 3 januar 2010 saa kommer der tre records i contractdates med contractid = 25, en for hver af de tre datoer.  Hvis du siger SELECT date FROM contract JOIN contractdate on contract.id = contract.contractid WHERE contract.id = 25 saa faar du de tre datoer.  Hvis du siger SELECT contract.id from contract JOIN contractdates ON contract.id = contractdates.contractid WHERE date = '2010-01-01' saa faar du contract 25 plus alle andre contracts der finder sted 1 januar, og hvis du gentager queriren med 'WHERE date = '2010-01-02' faar du contract 25 igen.

For at teste lavede jeg nedenstaaende tabeller mestererbsUser, mestererbsGroups, mestererbsContract, og mestererbsContractdates.  Jeg indfoerte saa denne query: 

SELECT fornavn, efternavn, navn, date
FROM mestererbsContract c
JOIN mestererbsContractdates d ON d.contractid = c.id
JOIN mestererbsGroups g ON g.id = c.groupid
JOIN mestererbsUser u ON u.id = c.userid
WHERE date = '2010-01-01'

users og groups for alle contracts on 2010-01-01.  Naar jeg gentager querien med WHERE date = '2010-01-02' faar jeg de samme users, groups, og contracts for de contracts der finder sted baade 1 jan og 2 jan.  Er det det du vil opnaa?  Eller har jeg fattet dig forkert?

Her er mine tabeller og proeve-data:

CREATE TABLE mestererbsUser(id INT, fornavn VARCHAR(10), efternavn VARCHAR(10));
INSERT INTO mestererbsUser VALUES(1, 'Hans', 'Hansen');
INSERT INTO mestererbsUser VALUES(2, 'Jens', 'Jensen');
INSERT INTO mestererbsUser VALUES(3, 'Sven', 'Svensen');
INSERT INTO mestererbsUser VALUES(4, 'Anders', 'Andersen');

CREATE TABLE mestererbsGroups(id INT, navn VARCHAR(10));
INSERT INTO mestererbsGroups VALUES(1, 'group1');
INSERT INTO mestererbsGroups VALUES(2, 'group2');
INSERT INTO mestererbsGroups VALUES(3, 'group3');
INSERT INTO mestererbsGroups VALUES(4, 'group4');

CREATE TABLE mestererbsContract(id INT, groupid INT, userid INT);
INSERT INTO mestererbsContract VALUES(1, 1, 1);
INSERT INTO mestererbsContract VALUES(2, 1, 2);
INSERT INTO mestererbsContract VALUES(3, 1, 3);
INSERT INTO mestererbsContract VALUES(4, 2, 1);
INSERT INTO mestererbsContract VALUES(5, 3, 1);
INSERT INTO mestererbsContract VALUES(6, 3, 3);
INSERT INTO mestererbsContract VALUES(7, 3, 4);
INSERT INTO mestererbsContract VALUES(8, 4, 3);

CREATE TABLE mestererbsContractdates(id INT, contractid INT, date DATE);
INSERT INTO mestererbsContractdates VALUES(1, 1, '2010-01-01');
INSERT INTO mestererbsContractdates VALUES(2, 1, '2010-01-02');
INSERT INTO mestererbsContractdates VALUES(3, 1, '2010-01-03');
INSERT INTO mestererbsContractdates VALUES(4, 2, '2010-01-01');
INSERT INTO mestererbsContractdates VALUES(5, 3, '2010-01-01');
INSERT INTO mestererbsContractdates VALUES(6, 3, '2010-01-02');
INSERT INTO mestererbsContractdates VALUES(7, 3, '2010-01-03');
INSERT INTO mestererbsContractdates VALUES(8, 3, '2010-01-04');
INSERT INTO mestererbsContractdates VALUES(9, 4, '2010-01-01');
INSERT INTO mestererbsContractdates VALUES(10, 5, '2010-01-01');

SELECT fornavn, efternavn, navn, date
FROM mestererbsContract c
JOIN mestererbsContractdates d ON d.contractid = c.id
JOIN mestererbsGroups g ON g.id = c.groupid
JOIN mestererbsUser u ON u.id = c.userid
WHERE date = '2010-01-01'
Avatar billede MesterErbs Nybegynder
11. februar 2010 - 09:12 #2
Mange tak for rigtig godt og fyldigt svar Christian. Du har forstået opgaven helt rigtigt!
Jeg tror du har fuldstændig ret i at det i virkeligheden måske er mig der har grebet den forkert an i min tabel struktur. Det giver bestemt mening at lave en record for hver dato. En contract kan nemlig godt have flere dato'er, hvilke der selvfølgelig også skal vises i kalenderen.

Det giver mig dog bare et andet problem andet sted i systemet, da jeg har en lignende kalender for de artister som er tilknyttet groups på contracts. Denne kalender er nemlig bygget på den måde jeg har skitseret og fungere egentlig fint. I denne kalender krydser artisterne dage af de ikke kan spille og disse dage kan jeg så ikke oprette en contract for den pågældende gruppe.
Jeg vil mene at jeg er nødt til at bygge samme stuktur for denne table også?
Jeg vil lige prøve at bygge om efter dit udkast og vende tilbage!
11. februar 2010 - 10:54 #3
Jeg tror du blander to ting sammen, tabellerne inde i databasen og saa den maade du traekker data ud og presenterer dem.  Hvis du soerger for at database tabellerne gengiver strukturen af og relationer mellem data-elementerne saa kan du traekke data ud og presentere dem paa 'alle' mulige maader.

Hvordan ser artisterne kalenderen?  Jeg gaar ud fra at artisterne ikke selv gaar ind og manipulerer med databasen, du laver vel en html formular paa en hjemmeside eller lignende.  Hvis en artist kan komme paa tale for de eventer der har contract id 3 og 8 saa traekker du data ud af databasen som SELECT  * FROM Contractdates WHERE id = 3 UNION Select * FROM Contractdates WHERE id = 8.  De udtrukne data placerer du i din html formular med et ekstra inputfelt for hver contractdate.  Artisterne krydser saa de contractdates af hvor de er interesserede i kontrakter.  Du har vel en tabel over artister.  Saa lav for eksempel en tabel ArtistAvailable med felter for artistid og Contractdatesid. De dage en artist er interesseret i kontrakt indsaetter du saa i den tabel med en query saa som:  INSERT INTO ArtistAvailable VALUES($artistid, $contractdateid) hvor $artistid og $contractid er variable du tager fra besvarelserne fra artisterne.

Foroevrigt (jeg ved at det spurgte du ikke om) tyder tabelnavnene Contract og ContractDates ogsaa paa sammenblanding af datastruktur og presentation fordi en event noedvendigvis maa eksistere, i hvertfald i en plan, foer der kan vaere tale om nogen kontrakt.  Ellers har du jo ikke noget at vise artisterne.  Naar saa du presenterer dine EventsDates til artisterne og faar dine availabilities saa finder der vel forhandlinger sted der kan resultere i en kontrakt.  Oplysninger om indgaaede kontrakter vil du vel bevare i en saerskilt tabel med contract nummer, artist, beloeb, vurdering (blev kontrakten tilfredsstillende opfyldt eller var det problemer, betaling, o.s.v.  Du kan jo saa vaelge at udvide din EventDates tabel med et ekstra felt der henviser til Contractid for de eventdates for hvilket en kontrakt kommer paa plads.  Hvis du ikke faar en artist til en planlagt eventdate bliver den maaske aflyst.  Hvis du saa vaelger at slette aflyste eventdates fra tabellen bliver der til sidst sammenfald mellem eventdates og kontrakter, men under planlaegnings- og forhandlings forloebet vil du have brug for oplysningerne (og du kan da ogsaa vaelge ikke at slette aflyste eventdates saa du har historiske informationer hvis du senere skal analysere hvad der skete med hvilke typer events og om du skal tilpasse udbuddet o.s.v.
Avatar billede MesterErbs Nybegynder
11. februar 2010 - 13:08 #4
1) Min artistcalender ser nogenlunde ud som du selv har beskrevet tidligere:
id userid date date date md yy  comments
1  23    [25] [26] [27] 01 2010 Dato relateret kommentar
Jeg tror det vil være mere hensigtsmæssigt at ændre denne til din beskrevne form:
id contractid date
1  253        2010-02-15

2) Min database er noget mere omfangsrig.
Hele mit kartotek ligger i groups fordelt på typer. Til hver gruppe er der så koblet et antal users til via en relations tabel også fordelt på usertypes. Det betyder at alle grupper og alle personer er unikke. Hver user har kan så tilføje "off days" til usercalender. Dvs. datoer de ikke kan spille. Forhandlingen foregår mellem  arrangøren og agenturet (mig). Når forhandlingen er afsluttet, opgradere jeg blot contract, og den får et fortløbende contractno.
Db ser således ud hvis du er interesseret:
groups
grouptype
user
usertype
userrel
usercalendar
contracts
contractdates

Umiddelbart er der ikke nogen grund til relation mellem usercalender og contractdates, da usercalendar blot er en information til agenten der skal booke jobbet. Ingen contracts bliver slettet, men bare "aflyst" hvilket netop betyder at sagshistoriken fastholdes.

Jeg skal til at have bygget hele systemet om og ved godt at strukturen ikke er den bedste, da det er et system jeg har bygget oven på de sidste 10 år og i en håbløs kodning, men det er smart og er blevet en stor succes blandt agenturer der skal holde styr på deres kontrakter, artister oa.
Jeg skal have proff hjælp til rekonstruktionen, men i første omgang skal det bare virke så dem der bruger det i dag er glade.

Jeg arbejder med ny dato struktur nu og håber på jeg kan få det til at spille senere i dag.
11. februar 2010 - 13:25 #5
Ok.  Dit oprindelige spoergsmaal var hvordan du fik vist events naar der er flere datoer til en event.  Jeg svarede ved at anbefale at lave strukturen af tabellen contractdates om og demonstrerede hvordan det ville hjaelpe til at traekke de oenskede data ud.  Du synes at have erkendt dette, og du synes at have mod paa at arbejde videre i den retning.  Vi har saa udvidet diskussionen til at omfatte visse andre tabeller.

Er det et passende tidspunkt til at afslutte DETTE spoergsmaal?  Yderligere problemer du matte rende ind i boer saa formuleres som nye spoergsmaal til Ekspertens medlemmer hvoraf nogle maaske er klogere end jeg.

Under alle omstaendigheder success med forehavendet.
Avatar billede MesterErbs Nybegynder
11. februar 2010 - 13:35 #6
Har netop efterprøvet dit oplæg og det ser udtil at det virker. Tak skal du have og du får selvfølgelig dine points.
Jeg opretter nyt spørgsmål hvis jeg har brug for yderligere hjælp.
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

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