26. februar 2016 - 13:48Der er
27 kommentarer og 1 løsning
Hjælp til oprettelse af forespørgsel
Hej
Jeg har problemer med oprettelse af en forespørgsel. Det er lidt noget bøvl at forklare, men jeg forstår ikke, hvordan man indsætter billeder. Kan det ikke lade sig gøre, som på andre forums, hvor man bare uploader det?
Nå men jeg har en forespørgsel, som bygger på indhold fra 2 tabeller.
Tabel 1: Overordnede oplysninger omkring ordrer. Én linje pr. ordre.
Tabel 2: Den detaljerede historie for hver enkelt ordre. En af kolonnerne har en kode, der angiver status/trin for ordren, og en af de øvrige kolonner angiver tidspunkt for den pågældende status.
De 2 tabeller er bundet sammen med ordrenr. som nøgle.
Nu ønsker jeg en forespørgsel som viser mig tidspunktet for de forskellige status/trin i én linje for hver ordre:
Kolonne 1: Ordrenr. (fra tabel 1) Kolonne 2: Tidspunkt for oprettelse af ordren (statuskode 1) (fra tabel 2) Kolonne 3: Tidspunkt for færdiggørelse af ordren (statuskode 2) (fra tabel 2) Kolonne 4: Tidspunkt for forsendelse af ordren (statuskode 3) (fra tabel 2)
I kolonne 2 indsætter jeg derfor feltet [Tidspunkt], og som kriterie for dette ønsker jeg, at [Statuskode] = 1. Da denne statuskode godt kan være repræsenteret flere gange for samme ordre, så ønsker jeg, at tidspunktet skal være det første/minimum for den pågældende status kode.
Det jeg har gjort er:
Felt = [Tidspunkt] Tabel = 2 Total = Min
Kriterier: [Statuskode] = 1
Problemet er (at jeg helt sikkert ikke har styr på det her...), at jeg får en fejlmeddelelse: Du har forsøgt at køre en forespørgsel, der ikke medtager det angivne udtryk ...... som en del af en aggregatfunktion.
Jeg vil gerne pointere, at jeg ikke er særlig god til Access og ikke forstår mig på VB programmering. Udtryksgeneratoren er, synes jeg, meget lidt brugervenlig, så jeg gætter mig ofte frem, hvilket er ret begrænsende for mulighederne.
Du kan ikke indsætte et kriterie i en kolonne, hvor kriteriet ikke passer til feltværdien (i en tidspunkt-kolonne kan kriteriet kun være et tidspunkt). Derfor: - Slet kriteriet fra tidspunkt kolonnen - Opret en ny kolonne med Felt=Statuskode og Kriterie=1. Totalen skal være "Hvor" og fjern X'et (vis ikke).
I kolonne 2 indsætter jeg derfor feltet [Tidspunkt], og som kriterie for dette ønsker jeg, at [Statuskode] = 1. Da denne statuskode godt kan være repræsenteret flere gange for samme ordre, så ønsker jeg, at tidspunktet skal være det første/minimum for den pågældende status kode.
Så statuskode = 1 er tidspunkt for hvornår ordren er oprettet. Men du kan så oprette samme ordre flere gange som jeg læser det. Jeg vil foreslå, at du ser på det problem først, så du ikke skal lave krumspring i dine senere sql fordi du har fejl tidligere i processen :)
Jeg vil bestemt give dig ret i at kodegeneratioren har sig eget liv ;) men lige netop det her problem er et spørgsmål om relationen mellem 2 tabeller OG at du opretter nye poster på den rigtige måde.
Skriv lidt mere om dine tabeller, så er det lettere at hjælpe dig med opbygningen af din sql
terry: Jeg kan ikke sende databasen af flere årsager. Datasikkerhed er den ene, da det er fortroligt data. Det andet er, at databasen er bygget op vha. sammenkædede tabeller (tabeller fra vores ordresystem via ODBC), så jeg tror ikke, at det vil virke.
Jeg kan alternativt sende et skærmprint af forespørgslen.
fdata:
Den løsning har jeg også været forbi, men så er udfordringen, at jeg efterfølgende vil have mulighed for at oprette flere kolonner, som igen er afgrænset af, at statuskoden nu er en anden (2, 3, etc.). Derfor skal det være i samme kolonne.
Men kan det ikke lade sig gøre, ja så er det jo sådan.
petersen7913: Jeg forstår din mening, men der er en mening med "galskaben" :-) Selve ordreoprettelsen sker selvfølgelig kun én gang, men andre ændringer i ordrestatus kan helt naturligt ske flere gange. Det kan være en ændring i ordren, en overførsel fra ordre- til produktionssystem, etc. Der vil derfor uundgåeligt være flere linjer med samme statuskode for hver ordre.
Kan du evt. give mig et hint omkring de oplysninger om tabellerne, som du er ude efter?
PS: Er der en vejledning i hvordan man lægger billeder op herinde? Går ud fra at de skal uploades på nettet først og så skal der linkes.
Et lille eksempel med 2 tabeller, 3 basisforespøglser og 1 forespørgsel, der samler data:
tblMain: Id autunumerering txt Tekst
tblDetail Id autunumerering MID Tal - link til tblMain Dato Dato Status kort tekst 1,2,3
For at afgrænse første forekomst af en status: Q1: SELECT tblMain.Id, Min(tblDetail.Dato) AS MinOfDato, tblDetail.Status FROM tblMain LEFT JOIN tblDetail ON tblMain.Id = tblDetail.MID GROUP BY tblMain.Id, tblDetail.Status HAVING (((tblDetail.Status)="1"));
Lav tilsvarende Q2 og Q3 for status 2 og 3
For at samle dem og få dato/status på en linie pr ordre: SELECT q1.Id, q1.MinOfDato, q1.Status, q2.MinOfDato, q2.Status, q3.MinOfDato, q3.Status FROM (q1 LEFT JOIN q2 ON q1.Id = q2.Id) LEFT JOIN q3 ON q1.Id = q3.Id;
Jeg har prøvet dette af hvor ordre 1 har alle 3 status, ordre 2 har status 1 og 2 og ordre 3 har kun status 1
Hvis jeg forstår dit indlæg #5 korrekt, så er du helt på sporet :-)
Mht. indlæg #6 så afprøver du mig noget ud over nuværende evner :-) SQL er delvisk russisk. Forstår lidt af det, men kan absolut ikke selv skrive noget i det :-)
Jeg tror dog måske, at jeg fatter pointen. Du vil have mig til at oprette en forespørgsel for hver status jeg ønsker et tidspunkt for i stil med det fdata er inde på længere oppe. Herefter opbygger jeg en forespørgsel, som indhenter oplysningerne fra de førnævnte underforespørgsler. Det giver mening for mig, men er det det du mener?
terry: Okay. Jeg har ingen konto pt. så ser lige om der findes en løsning inden jeg opretter mig. Er det ikke lidt Old School at et IT forum ikke har en upload funktion af billeder? Måske det bare ikke er nørdet nok :-D
j-kid - jeg vil absolut anbefale dig at sætte dig ind i SQL. Det er helt basalt at man kan forstå strukturen i en database og hvordan man kan trække data ud.
SQL kunne da klart være fedt at kunne. Lige nu står jeg bare lige med et problem der skal løses, og så ender jeg som oftest med at komme fra det igen, når først det akutte behov er løst :-)
Hvad kan du anbefale af litteratur?
fdata:
Jeg har oprettet forespørgsel som foreslået. Nedenfor er vist resultat, hvis jeg vælger "Grupper efter" og Tidspunkt er sat til "Grupper efter" også. Så får jeg flere linjer for hver kode.
Ændrer jeg til eks. "Første", så fås kun én linje pr. ordre, men jeg har brug for at kunne veksle imellem "Første" og "Sidste" alt efter hvilken statuskode jeg er ude efter.
Tænker jeg er lidt tilbage i petersen7913's idé omkring underforespørgsler.
Formålet med hele øvelsen er i øvrigt, at jeg kan importere forespørgslen i Excel, hvor jeg vil analysere nærmere på, hvordan de enkelte ordres forløb er med henblik på at optimere en produktion yderligere.
Der er jo tit mange veje til Rom ;) når du er meget grøn mht. SQL vil jeg foreslå at du arbejder med (små) overskuelige queries, så du hele tiden har overblik over hvad du gang i. Og så kan du sætte dem sammen og få det du har brug for.
Efterhånden kan du så lave de mere avancerede ting og stadig vide hvad du laver.
Jeg tror at det vigtigste at forstå ved SQL er, at det er MÆNGDER man arbejder med.
Umiddelbart kan du ikke "veksle imellem "Første" og "Sidste" alt efter hvilken statuskode jeg er ude efter"; men du kunne vel nøjes med at oprette 2 forespørgsler: - en med "Første" - og en med "Sidste"
fdata: Ser først dit indlæg nu. Det er muligt, at det kan gøres sådan. Tror dog jeg vil få problemer, når nu jeg ønsker, at der kun skal være én linje pr. ordre.
Status: Jeg har nu opbygget forespørgslen som en hovedforespørgsel, med en del underforespørgsler for hver statuskode. Ser ud til næsten at virke :-)
Jeg har dog det problem, at hvis en status ikke findes for ordren, så får jeg en blank linje.
Eks. Jeg ønsker at vide, hvis en ordre har været ændret efter oprettelsen. Lad os kalde det status 4. Hvis nu ordren aldrig har været ændret efter oprettelsen, så kommer ordren ikke med i min forespørgsel. Hvis jeg oversætter til Excel sprog, så vil det være en slags:
=hvis([tidspunkt for ændring] = ""; 0 ; [Tidspunkt for ændring])
Slet ingen der kan hjælpe mig sidste skridt i mål? :-)
Lad mig beskrive en af underforespørgslerne.
Der er 2 tabeller. En ordretabel og en historik tabel. De 2 tabeller er joinet via ordrenr.
Kolonne 1 Ordrenr. [Fra ordretabel] Kolonne 2 Status code [Fra historik tabel] Kolonne 3 Tidspunkt for ovenstående status code [Fra historik tabel]
Hvis den pågældende status code ikke er tilgængelig på den pågældende ordre, så vil jeg have forespørgslen til at returnere et 0. Lige nu returnerer den en blank forespørgslen, hvilket resulterer i, at ordren slet ikke medtages i hovedforespørgslen, selvom de øvrige status koder for samme ordrenr., ikke er blanke.
Det er det sidste jeg mangler, så jeg kan lukke spørgsmålet :-)
Jeg er frisk; men skal vi ikke prøve at spole tilbage til problemets kerne:
- Hvor mange statuskoder taler vi om? Er det kun de 3 eller er der flere? - Du vil gerne "veksle mellem første og sidste". Er der en form for regler her - altså at en bestemt statuskode er bundet til enten "første" eller "sidste"? - Eller vil du skifte mellem "første" og "sidste" for alle koder samtidig? - Manglende data skal medføre et 0 (nul) i et datofelt?!?
Kan du prøve at poste et eksempel på hvordan du forestiller dig resultatet ville se ud (vis det som en lille tabel)?
(Du skal i øvrigt nok bestræbe dig på at formulere spørgsmålene lidt klarere. Når du skriver "Tidspunkt for ovenstående status code" mener du vel "Første tidspunkt for ovenstående status code" eller hvad?)
Undskyld jeg først vender tilbage nu. Hele huset skulle lige igennem en omgang forårs halsbetændelse...
Der er flere statuskoder end 3. De har alle deres egen underforespørgsel. For hver underforespørgsel er reglen omkring første eller sidste den samme. Her veksles ikke.
Hvis vi prøver at holde de underliggende status forespørgsler udenfor, så indeholder selve hovedforespørgslen alle ordrer, som er udvalgt ud fra en datobetingelse. Lad os sige, at jeg får 100 ordrer ud, som opfylder betingelserne.
Nu kobler jeg hovedforespørgslen samme med underforespørgslerne, så jeg får et tidspunkt for de forskellige status'er. Hvis nu én af de 100 ordrer ikke har været ændret, dvs den underforespørgsel med status 2 ikke indeholder ordren, så fjernes ordren som det er nu i hovedforespørgslen. Det er ikke ønskværdigt. Jeg ønsker, at beholde ordren i hovedforespørgslen, men feltet hvor dato/tidspunkt for statuskode 2 vises, skal være blankt, da ordren aldrig har været ændret.
Vi lægger os op ad #6 og opretter de to tabeller. For overskuelighedens skyld opretter vi kun 3 underforespørgsler. Q1 en er "første-forespørgsel" (Min), de to andre er "sidste-forespørgsler" (Max).
Q1: SELECT tblDetail.Mid, tblMain.Id, Min(tblDetail.Dato) AS D FROM tblMain LEFT JOIN tblDetail ON tblMain.Id = tblDetail.MID WHERE (((tblDetail.Status)="1")) GROUP BY tblDetail.Mid, tblMain.Id;
Q2:SELECT tblDetail.Mid, tblMain.Id, Max(tblDetail.Dato) AS D FROM tblMain LEFT JOIN tblDetail ON tblMain.Id = tblDetail.MID WHERE (((tblDetail.Status)="2")) GROUP BY tblDetail.Mid, tblMain.Id;
Q3:SELECT tblDetail.Mid, tblMain.Id, Max(tblDetail.Dato) AS D FROM tblMain LEFT JOIN tblDetail ON tblMain.Id = tblDetail.MID WHERE (((tblDetail.Status)="3")) GROUP BY tblDetail.Mid, tblMain.Id;
Du samler dem så med en UNION (som er lidt anderledes end den tidligere beskrevne!)
SELECT tblMain.txt, q1.D AS Status_1, q2.D AS Status_2, q3.D AS Status_3 FROM ((tblMain LEFT JOIN q1 ON tblMain.ID = q1.mID) LEFT JOIN q3 ON tblMain.ID = q3.mID) LEFT JOIN q2 ON tblMain.ID = q2.mID ORDER BY Txt;
Nu burde du se udfyldte datoer for de status'er du har oprettet i tblDetail - og tomme felter, hvor der ikke er oprettet en status.
(Jeg går ud fra at du selv kan ændre første/sidste-kriterierne og eventuelle feltnavne)
Tak. Jeg kan se der er lagt noget energi i svaret :-)
Jeg har bare ualmindeligt svært ved at forstå, hvad det er det går ud på. Det bunder helt sikkert i mine ikke eksisterende evner i SQL. Jeg laver alt i forespørgselsdesigneren, hvor det er mere grafisk, men jo nok også begrænsende.
Har du bygget selve databasen op? Tænkte at jeg måske kunne se mig ud af det, hvis du har lavet databasen for testens skyld og kan maile den til mig?
Alternativt må jeg se om jeg kan finde ud af at lægge noget billede op og så linke til det. Det siger nok mere end meget tekst.
Jeg har kopieret SQL koden fra den første af mine underforespørgsler. Den ser sådan ud:
SELECT LIORDER_AUF_KOPF.AUF_NR, LIORDER_AUF_KOPF.LIEFE_DAT_KU, LIORDER_ORDHIST.STATUS_CODE, First(LIORDER_ORDHIST.CREATED) AS [Order created], LIORDER_ORDHIST.REF_NO1 AS [Order created_info] FROM LIORDER_AUF_KOPF INNER JOIN LIORDER_ORDHIST ON LIORDER_AUF_KOPF.AUF_NR = LIORDER_ORDHIST.ORDER_NO GROUP BY LIORDER_AUF_KOPF.AUF_NR, LIORDER_AUF_KOPF.LIEFE_DAT_KU, LIORDER_ORDHIST.STATUS_CODE, LIORDER_ORDHIST.REF_NO1 HAVING (((LIORDER_ORDHIST.STATUS_CODE)=1));
Statuskoden i forespørgslen er 1 svarende til oprettelse af ordren.
Er den som udgangspunkt ok eller er der ting her der skal rettes til?
Mht. svigtende evner: Vi bliver allesammen klogere hver dag!
Dagens Access-tip: Åbn en forespørgsel i Design mode, klik på Vis (helt oppe til venstre) og vælg SQL-visning. Så ser du de SQL-sætninger, som forespørgslen i virkeligheden består af. Man kan også rette i udtrykket - og frit skifte frem og tilbage mellem Design og SQL.
Jeg har først lige haft tid til at rode med det nu. Det viser sig, at årsagen til min manglende succes er join forbindelserne. Her "peger" dine i en bestemt retning, hvor jeg ikke har haft angivet noget. Jeg forsøgte, men fik en fejlmeddelelse hver gang. Årsagen til dette var, at jeg ikke angav samme kriterie for alle forbindelserne.
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.