Nestede søk. Nestede søk arbeider med batch-søk

Nestede søk. Nestede søk arbeider med batch-søk

Denne artikkelen er ment for lesere som er kjent med SQL-språket.

Spørrespråket 1C, brukt siden versjon 8, har i dag blitt et nyttig verktøy for å jobbe med databaser, som lar deg lese fra dem, men ikke skrive. Syntaktisk er spørringsspråket veldig likt SQL-språket, men på russisk.

Nedenfor er en tabell over samsvar mellom hovedspørringsspråket og SQL-operatører:

1C spørringsspråkoperatører

SQL-setning

DIVERSE

FORBINDELSE

GRUPPE AV

KOMBINERE

SORTER ETTER

Og dette er ikke en fullstendig liste. Mer fullstendig referanseinformasjon om tilgjengelige spørringsspråkoperatører kan fås i spørringsdesigneren, som vil bli diskutert nedenfor.

Utførelse av en 1C-forespørsel fra programkode utføres ved å bruke det innebygde språkobjektet "Request". Et eksempel på å skrive en databasespørring ved å bruke det innebygde programmeringsspråket:

Request = Ny forespørsel; Query.Text = "VELG | Synonym.Link AS Link |FROM | Directory.Directory1 AS Synonym"; Select = Query.Run().Select(); While Selection.Next() Loop // Sett inn utvalgsbehandling SelectionDetailedRecords EndCycle;

"Run"-metoden utfører spørringen, "Select"-metoden returnerer en verdi av typen "SelectFromQueryResult". Du kan også bruke Unload-metoden, som returnerer en tabell med verdier.

Forespørselsparametrene lagres i "Parameters" -egenskapen (i dette tilfellet er dette en struktur, så alle strukturmetoder kan brukes her - sett inn, slett, etc.).

Et eksempel på innstilling av parameteren «Query.Parameters.Insert» («Directory», DirectoryLink). I forespørselen kan du få tilgang til parameterne ved å bruke og-tegnet "&Directory". Nedenfor er et eksempel på en forespørsel som bruker parametere:

Request = Ny forespørsel; Query.Text = "SELECT | Users.Link AS Link, | Users.Parent AS Parent, | Users.Name AS Name |FROM | Directory.Users AS Users |WHERE | Users.Link = &Directory"; Query.Parameters.Insert("Directory", DirectoryLink); Select = Query.Run().Select(); While Selection.Next() Loop // Sett inn utvalgsbehandling SelectionDetailedRecords EndCycle;

La oss huske at spørringsspråket kun er ment for å lese data fra databasen, så det har ikke analoger til slike SQL-setninger som INS ERT og UPDATE. Data kan bare endres gjennom objektmodellen til det innebygde 1C-programmeringsspråket. Også i 1C-spørringsspråket er det operatører som ikke har noen analoger i SQL, for eksempel:

  • I HIERARKIET
  • PLASS
  • INDEKSER ETTER

I HIERARKIET– lar deg velge alle elementene i den hierarkiske katalogen som er inkludert i hierarkiet til den overførte lenken. Eksempel på forespørsel ved bruk av I HIERARKIET:

SELECT Products.Link, Products.Article FROM Directory.Products AS Products WHERE Products.Link IN HIERARKI(&CITrus)"

I dette tilfellet vil resultatet returnere alle underordnede elementer i Citrus-nomenklaturkatalogen, uansett hvor mange hierarkinivåer denne katalogen har.

Også, for eksempel, er oppgaven å finne et produkt med navnet "Pen". Produktet må inkluderes i hierarkiet "Stasjonary". Varer», det vil si at vi ikke trenger å se etter dørhåndtaket. Strukturen til nomenklaturen i dette tilfellet er som følger:

Kontor

|_ Fyllepenner |_ Rød penn |_ Blå penn |_ Blekkpenner |_ Linjaler

Tilbehør

|_ Dørhåndtak |_ Enkelt dørhåndtak |_ Luksus dørhåndtak

Vi skriver følgende forespørsel:

VELG Products.Link, Products.Article FROM Directory.Products AS Products WHERE Products.Name Like "Pen%" AND Products.Link IN HIERARKI(&Stasjonary)"

Når du bruker designet I HIERARKIET det er nødvendig å ta hensyn til at hvis du sender en tom lenke til "Office" -parameteren, vil utførelsen av forespørselen reduseres, siden plattformen vil sjekke hvert element for å se om det tilhører roten.

PLASS– Denne uttalelsen plasserer resultatet i en midlertidig tabell. Eksempelforespørsel:

SELECT Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name PLACE SelectedUsers FROM Directory.Users AS Users WHERE Users.Link = &Directory; SELECT SelectedUsers.Link AS Link, SelectedUsers.Parent AS Parent, SelectedUsers.Name AS Navn FRA SelectedUsers AS SelectedUsers

Denne SQL-spørringen vil bli utført av flere spørringer:

  • Opprette en midlertidig tabell (plattformen kan "gjenbruke" tidligere opprettede midlertidige tabeller, så opprettelse skjer ikke alltid);
  • Plassering av data i en midlertidig tabell;
  • Utfører hovedspørringen, nemlig SEL ECT fra denne midlertidige tabellen;
  • Ødelegge/rengjøre et midlertidig bord.

En midlertidig tabell kan bli ødelagt eksplisitt gjennom konstruksjonen ØDELEGGE, eller implisitt - når du lukker den midlertidige tabellbehandleren.

"Query"-objektet til det innebygde programmeringsspråket har en egenskap "Temporary Table Manager", som er beregnet for arbeid med midlertidige tabeller. Eksempelkode:

MVT = New TemporaryTableManager(); Request = Ny forespørsel; Query.TemporaryTableManager = MVT;

Etter å ha utført en spørring, kan MVT-variabelen brukes en gang til i en annen spørring, noe som utvilsomt er en annen fordel med å bruke midlertidige tabeller. I dette tilfellet vil den midlertidige tabellen fra databasen bli slettet når "Lukk"-metoden kalles...

MVT.Close();

...eller når du sletter en variabel fra minnet, det vil si når du utfører metoden der variabelen ble deklarert. Midlertidige tabeller øker belastningen på diskundersystemet, så du bør ikke lage for mange midlertidige undersystemer (for eksempel i en løkke), eller store volumundersystemer.

INDEKSER ETTER– denne operatøren brukes sammen med operatøren PLASS. Når du oppretter en midlertidig tabell, kan denne operatøren indeksere tabellen som opprettes, noe som gjør arbeidet med den betydelig raskere (men bare hvis indeksen samsvarer med søket ditt).

Gratis ekspertkonsultasjon

Takk for din forespørsel!

En 1C-spesialist vil kontakte deg innen 15 minutter.

Funksjoner til noen spørringsspråkoperatører

FOR ENDRING– denne operatøren er ment å låse en spesifikk spørringstabell (eller alle tabeller som deltar i spørringen). Låsing oppnås ved å bruke en U-lås på bordet. I SQL implementeres dette via hint UPDLOCK. Denne utformingen er nødvendig for å forhindre vranglås. Eksempel på forespørsel med en konstruksjon FOR ENDRING:

VELG Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name FROM Directory.Users AS Users LEFT JOIN Directory.RFK AS RFK BY Users.RFK = RFK.Link TO CHANGE Directory.Users

I dette eksemplet vil U-låsen plasseres på brukerbordet. Hvis du ikke spesifiserer en tabell for en lås, vil den bli pålagt alle tabeller som deltar i spørringen. Det er viktig å merke seg at denne utformingen bare fungerer i konfigurasjoner der den automatiske låseadministrasjonsmodusen er aktivert.



FORBINDELSE– forespørselen støtter tilkoblinger VENSTRE/HØYRE, FULL, INDRE, som tilsvarer joins i SQL – LEFT/RIGHT JOIN, OUTTER JOIN, INNER JOIN.

Men når du bruker spørringsbyggeren vil du ikke kunne gjøre det HØYRE BLI MED. Konstruktøren vil ganske enkelt bytte bord, men operatøren vil alltid være venstrehendt. Av denne grunn vil du aldri se bruken av en right join i 1C.

Syntaktisk ser forbindelsen slik ut:

VELG Table1.Link AS Link FROM Directory.Directory1 AS Table1 VENSTRE JOIN Directory.Directory2 AS Table2 BY Table1.Attributes = Table2.Attributes

1C-spørringsspråket har ingen operatør for å bli med i et kartesisk produkt (CROSS JOIN). Fraværet av en operatør betyr imidlertid ikke at spørringsspråket ikke støtter en slik forbindelse. Om nødvendig kan du bli med i tabeller slik:

SELECT Table1.Link AS Link FROM Directory.Directory1 AS Table1 LEFT JOIN Directory.Directory2 AS Table2 BY TRUE

Som det fremgår av eksempelet, er tilkoblingsnøkkelen satt AV SANT, det vil si at hver rad i en tabell tilsvarer en rad i en annen. Type sammenføyning (LEFT, RIGHT, FULL, INNER) er ikke viktig hvis du har rader i begge tabellene, men hvis det ikke er noen rader i en av tabellene (la oss si tabellen) - blir resultatet annerledes. For eksempel ved bruk INNVENDIG tilkoblingsresultatet vil være tomt. Ved hjelp av VENSTRE HØYRE resultatet av sammenføyningen vil være eller ikke være data avhengig av hvilken tabell vi kobler til - med data eller ikke. Ved hjelp av FULL Dataene vil alltid være tilkoblet (naturligvis bare fra én tabell, siden den andre er tom) avhenger av den spesifikke applikasjonsoppgaven.

Et lite visuelt hint om hvordan de forskjellige tilkoblingstypene fungerer:



SOM. I motsetning til den lignende SQL-operatøren - LIKE, malen for SOM kan spesifiseres med bare noen spesialtegn:

  • % (prosent): en sekvens som inneholder et hvilket som helst antall vilkårlige tegn;
  • _ (understrek): ett vilkårlig tegn;
  • / - neste tegn skal tolkes som et vanlig tegn.

RESULTATER AV PROGRAMVAREN SQL-analogen er ROLLUP-operatøren. Eksempel på operatørbruk RESULTATER:

SELECT Products.Price AS Pris, Products.Product AS Produkt FRA Directory.Nomenclature AS Produkter RESULTATER GJENNOMSNITTLIG (PRIS) ETTER Produkt

Resultatet blir slik:

Seng

9833,333

Jern

Penn

Det vil si at en ekstra linje legges til resultatet som inneholder verdien av feltet som grupperingen utføres med og verdien til aggregeringsfunksjonen.

Arbeid med batchforespørsler

1C lar deg jobbe med grupper av forespørsler. I en batchforespørsel er forespørselstekster atskilt med semikolon (;). 1C batchforespørselen utføres sekvensielt. Eksempel på batchforespørselstekst:

SELECT Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name FROM Directory.Users AS Users;
VELG Arbeidsplan.Bruker AS Bruker, Arbeidsplan.Dato AS Dato, Arbeidsplan.Arbeidstider AS Arbeidstid FRA Registrer informasjon.Arbeidsplan AS Arbeidsplan

For å få resultatet av alle spørringene som er inkludert i en pakke, må du bruke «ExecutePackage»-metoden til forespørselsobjektet, i stedet for «Kjør». Denne metoden utfører alle forespørsler sekvensielt. Spørringsresultatet er en rekke resultater for hver spørring i pakken, og sekvensen for plassering i matrisen er den samme som sekvensen av spørringer i pakkens tekst.

Når du vurderer et spørringsspråk, er det verdt å nevne en slik funksjon som virtuelle tabeller. Virtuelle tabeller er ikke til stede i databasen, de er en slags wrapper som kjøres på DBMS-siden som en spørring ved hjelp av underspørringer. Eksempel på en 1C-spørring som bruker virtuelle tabeller:

SELECT RegisterLiabilitiesTurnovers.Liability AS Liability FROM RegisterAccumulations.RegisterLiabilities.Turnover() AS RegisterLiabilitiesTurnovers

En slik spørring til DBMS vil se slik ut:

SEL ECT T1.FLD25931RREF FR OM (SELECT T2._FLD25931RREF AS FLD25931RREF, Cast (Sum (T2._FLD25936) som numerisk (38, 8)) som FLD25936Turnover_ Numeric (38 (T2.___fld2593. AS Fld25937Turnover_ FR OM dbo._AccumRgTn25938 T2 WH ERE ((T2._Fld949 = @P1)) OG ((T2._Fld25936 @P2 OR T2._Fld25937 @P3.)_Fld25937 @P3.(Fld25937 @P3.)_Fld25.FLAST(Fld25.C d2 ) 5936 ) AS NUMERIC(38, 8))) 0,0 OR (CAST(SUM(T2._Fld25937) AS NUMERIC(38, 8))) 0,0) T1>>>>

Det kan ses at det ikke ser ut som SQL, siden det er en underspørring, gruppering. Virtuelle tabeller er stort sett "syntaktisk sukker", det vil si at de generelt er laget for å gjøre det lettere å utvikle spørringer, slik at spørringene er mer kompakte og mer lesbare.

Bare registre har virtuelle tabeller, men hvilke virtuelle tabeller som er tilgjengelige i et register kan ses i spørringsdesigneren.



Når du bruker virtuelle tabeller, må du alltid oppgi en valgbetingelse. Ellers kan det oppstå ytelsesproblemer.



I forespørselsteksten ser det slik ut:

Akkumulasjonsregister Omsetninger (, Drift = &Drift) AS Ansvarsregister Omsetning

For å gjøre det enklere å skrive spørringer, det vil si å lage spørringstekster, er det i 1C en konstruktør som kan kalles opp via kontekstmenyen (høyre museknapp):



I spørringsdesigneren kan du se en fullstendig liste over støttede spørringsspråkfunksjoner og -operatorer.


Query Builder er et veldig fleksibelt visuelt verktøy for å lage spørringer av enhver kompleksitet. Den er kun tilgjengelig i konfiguratormodus. I Enterprise-modus er det en såkalt "Query Console" - dette er ekstern prosessering levert på ITS-disken. For en administrert applikasjon kan spørringskonsollen lastes ned fra its.1c.ru.

En beskrivelse av å jobbe i spørringsdesigneren er utenfor rammen av denne artikkelen, så den vil ikke bli diskutert i detalj.

Årsaker til suboptimal søkeytelse

Nedenfor er en liste over hovedårsakene (men ikke alle) som fører til treg kjøring av spørringer.

  • Bruke sammenføyninger med underspørringer

Det anbefales ikke å utføre en sammenføyning med underspørringer bør erstattes med midlertidige tabeller. Sammenknytting av underspørringer kan føre til betydelige ytelsestap, og kjøring av spørringer på forskjellige DBMS-er kan variere betydelig i hastighet. Utførelseshastigheten til slike spørringer er også sensitiv for statistikk i DBMS. Årsaken til denne virkemåten er at DBMS-optimalisatoren ikke alltid kan bestemme den optimale planen for utførelse av spørringer, siden optimalisereren ikke vet noe om hvor mange rader underspørringen vil returnere etter utførelse.

  • Bruk av virtuelle tabeller i spørringssammenføyninger

Virtuelle tabeller på DBMS-nivå kjøres som underspørringer, så årsakene er de samme som i første avsnitt.

  • Bruke betingelser i en spørring som ikke passer til eksisterende indekser

Hvis i forespørselsbetingelsene (i operatøren HVOR eller virtuelle tabellbetingelser) bruker felt som ikke alle er inkludert i indeksen, vil denne spørringen bli utført ved hjelp av SQL-konstruksjonstabellskanningen eller indeksskanningen (helt eller delvis). Dette vil påvirke ikke bare utføringstiden for spørringen, men også en overdreven S-lås vil bli plassert på ekstra rader, som igjen kan føre til låseskalering, det vil si at hele tabellen vil bli låst.

  • Bruke OR i spørringsbetingelser

Bruke den logiske operatoren ELLER i design HVOR kan også resultere i en tabellskanning. Dette skjer fordi DBMS ikke kan bruke indeksen riktig. I stedet for ELLER du kan bruke designet KOMBINER ALT.

  • Motta data gjennom en prikk for felt av en sammensatt type

Det anbefales ikke å oppnå verdier gjennom en prikk (i konstruksjonen VELG HVOR), fordi hvis objektattributtet viser seg å være en kompleks type, vil sammenføyningen skje med hver tabell som er inkludert i denne komplekse typen. Som et resultat vil DBMS-spørringen være betydelig mer komplisert, noe som kan hindre optimalisereren fra å velge riktig utførelsesplan for spørringen.

Fra databasen i henhold til en bestemt betingelse. For å gjøre dette, i 1C 8.3 må du bruke nestede spørringer.

Men det bør huskes at i de fleste tilfeller er nestede spørringer i 1C ubrukelige uten å koble resultatene med andre tabeller. I nesten alle tilfeller vil en slik tilkobling i stor grad bremse utførelsen av forespørselen som helhet.

Et eksempel på en nestet spørring i et spørringsspråk

Jeg skal gi et eksempel på en nestet spørring for . La oss si at vi må prøve mengden av en viss saldo for individuelle kunder på en bestemt dato:

VELGE
Ikke-utbetaling av betalingssaldoer.
Ikke-forsendelseBetalinger Saldoer.BeløpBest
FRA

Få 267 videotimer på 1C gratis:

VENSTRE BLI MED Akkumuleringsregisteret. Manglende utbetalinger Saldo AS. Manglende utbetalinger
Software AttachmentRequest.LinkToRequestCustomers = Ubetalte betalingerBalances.Customer

Når DBMS utfører en slik spørring, er feil handlinger av optimalisereren mulig, siden det er vanskelig å bestemme en plan for behandling av spørringen. Når en DBMS kobler sammen to tabeller, bygger optimalisereren en algoritme basert på å beregne antall poster i disse tabellene.

Når en underspørring brukes, er det imidlertid svært vanskelig å beregne antall poster som returneres fra underspørringen.

Som er bedre?

// Midlertidig tabell
VELGE
Customers.Link HVORDAN Kunder
PLASS-fanen Kunder
FRA
Directory.Customers AS Kunder
WHERE Customers.Link B (&Customers)
;

// Hovedforespørsel
VELGE
tabClients.Link,
Ikke-betalingssaldoer.AmountBest,
FRA
tabCustomers HVORDAN tabCustomers
VENSTRE TILKOBLING Registrer akkumuleringer.
,
Kunde B
(VELGE
fanenKunder.Kunder
FRA
tabKunder)) HVORDAN Manglende betaling Betalingssaldo
ProgramvarefanenKunder.Kunder = Ubetalte betalingerSaldoer.Kunder

Se også videoopplæringen om nestede søk:

Nå vet optimizeren på forhånd hvor mange poster som er i den midlertidige tabellen, og optimerer enkelt tabellsammenføyningsalgoritmen.

Hvis du begynner å lære 1C-programmering, anbefaler vi vårt gratiskurs (ikke glem

Spørringsdesigneren i 1C 8.3 og 8.2 er et kraftig utviklingsverktøy. Den lar deg komponere en forespørselstekst ved å bruke et spesielt visuelt miljø. Derfor, for å lage en 1C-forespørsel, er det ikke nødvendig å kjenne det innebygde spørringsspråket, det er nok å navigere i det enkle og intuitive grensesnittet til designeren.

Spørringsbyggeren er et sett med faner, som hver er ansvarlig for sin egen del av spørringen. Så fyller ut fanen Tabeller og felt Vi velger tabeller hvorfra 1C-spørringen vil motta dataene og feltene i disse tabellene som er nødvendige for å løse et spesifikt problem. Fylling inn i murverket Forhold vi pålegger betingelser for de valgte tabellene for å velge fra dem bare dataene vi trenger, og så videre.

Beskrivelse av spørringsdesigneren på det offisielle 1C 8-nettstedet: v8.1c.ru

Tabeller og felt; ; ; ; ; ; Nestede søk (under utvikling).

For å ringe 1s 8 spørringsdesigneren i programkoden må du:

  • Opprett en ny forespørsel
Request = Ny forespørsel;
  • Angi en tom forespørselstekstlinje
Request.Text = "";
  • Plasser musepekeren mellom anførselstegnene og trykk på høyre museknapp. Velg elementet i kontekstmenyen som åpnes Spørringskonstruktør og svar Ja på spørsmålet om å opprette en ny forespørsel. Hvis forespørselsteksten allerede er skrevet ned, må du klikke hvor som helst i den og ringe konstruktøren ;

La oss se på alle hovedfanene til spørringsbyggeren ved å bruke små eksempler på økende kompleksitet. Denne tilnærmingen vil tillate en nybegynner 1C-programmerer å mer effektivt studere konstruktøren og alle dens evner. For eksempler vil vi bruke konfigurasjonen Regnskap 3.0.

Leksjon 1. Spørringsbyggeren er den enkleste brukssaken.

Oppgave: skriv en forespørsel til nomenklaturkatalogen, velg hele nomenklaturen til katalogen.

Nye faner: Tabeller og felt.

Nye mekanismer: se og redigere forespørselsteksten ved å bruke "Request"-knappen.

For å begynne å lage en forespørsel, la oss lage en ny forespørsel og ringe konstruktøren (som skrevet noen avsnitt ovenfor). Etter dette åpnes designervinduet på fanen Tabeller og felt.

Teoretisk del av leksjon nr. 1

Tab Tabeller og felt består av tre seksjoner:

Database. Denne delen presenterer alle databasetabellene som kan brukes til å bygge en spørring;

Tabeller. I denne delen er tabellene som er nødvendige for denne spørringen valgt. For deretter å flytte dem fra delen database trenger å:

  • Eller dobbeltklikk på bordet;
  • Eller bruk ">" eller ">>"-knappene.

Over avsnitt Tabeller Det er en rekke knapper. De fleste av dem vil bli diskutert mer detaljert i de følgende leksjonene. Foreløpig vil jeg bare gi korte forklaringer.

  • Opprett en underspørring(Rød linje). Designet for å lage en ny underspørring;
  • Lag en midlertidig tabellbeskrivelse(gul linje). Lar deg spesifisere navnet på en midlertidig tabell som er plassert utenfor denne spørringen, den kan også brukes til å sende en verditabell til spørringen;
  • Endre gjeldende element(grønn linje). Lar deg hoppe til den valgte underspørringen, den midlertidige tabellen eller den midlertidige tabellbeskrivelsen;
  • Fjern gjeldende element(blå linje). Fjerner den valgte tabellen fra de valgte tabellene;
  • Bytt bord(blå linje). Åpner dialogen for å erstatte den valgte tabellen. Nyttig hvis du har valgt feil register virtuell tabell, da posisjonering skjer på den gjeldende valgte tabellen i listen.
  • Virtuelle bordalternativer(lilla linje). Åpner virtuelle registertabellparametere.

Enger. Denne seksjonen velger tabellfelt fra forrige seksjon. Disse feltene vil være kolonnene i tabellen eller utvalget oppnådd som et resultat av spørringen. De er først og fremst nødvendige for å hente fra de utvalgte tabellene kun den informasjonen som er nødvendig i et bestemt tilfelle. For å flytte dem fra delen Tabeller som trengs:

  • Eller dobbeltklikk på feltet;
  • Eller bruk ">" eller ">>" knappene;
  • Du kan også legge til et nytt felt selv ved å bruke et vilkårlig uttrykk fra feltene til utvalgte tabeller og spørringsspråkfunksjoner.

Over avsnitt Enger Det er en rekke knapper. Å lage felt ved hjelp av vilkårlige uttrykk vil bli diskutert mer detaljert i de følgende leksjonene. Foreløpig vil jeg bare gi korte forklaringer.

  • Legg til(grønn linje). Designet for å legge til et nytt felt ved hjelp av friuttrykksredigering;
  • Endre gjeldende element(Rød linje). Lar deg endre det valgte feltet ved hjelp av redigeringsprogrammet;
  • Slett gjeldende(blå linje). Fjerner det valgte feltet fra listen.

Praktisk del av leksjon nr. 1

Vi har behandlet teorien som er nødvendig for å fullføre oppgaven i denne leksjonen. La meg minne deg på hvordan det høres ut: skriv en forespørsel til nomenklaturkatalogen, velg hele nomenklaturen til katalogen.

La oss begynne å lage en forespørsel om varer:

  • La oss lage en ny forespørsel og åpne konstruktøren ved å bruke metoden spesifisert i begynnelsen av leksjonen;
  • I kapittel Database, la oss åpne en tråd Kataloger og finn en guide der Nomenklatur;
  • Velg den og bruk «>»-knappen for å flytte den til delen tabeller;
  • I kapittel Tabelleråpne nomenklaturkatalogen ved å bruke "+"-ikonet;
  • Finn feltet i listen over felt som åpnes Link og flytt den til delen Enger ved å bruke ">"-knappen
  • Vareforespørselen er klar, klikk på "OK"-knappen nederst i designervinduet.

La oss se på hva det er nestede søk i og hvorfor de trengs.
Det er ofte en situasjon hvor flere sekvensielle handlinger må utføres på et bord. Et ganske illustrativt eksempel er når du først må, og deretter pålegge en vilkår på en gruppert tabell, eller koble den til en annen tabell. I slike tilfeller kommer de til unnsetning nestede søk.

Et nestet søk er praktisk talt ikke forskjellig fra et vanlig søk. Det er omsluttet av parentes, og nesten alle metoder og funksjoner i 1C-spørringsspråket er tilgjengelige i det. Og for den overordnede spørringen er alle feltene i underspørringen tilgjengelige.
Strukturen til den mest primitive nestede spørringen ser slik ut

VELG FRA (VELG FRA) SOM NestedQuery

Selvfølgelig, i dette skjemaet, gir det ikke mening å bruke en nestet spørring, fordi Du kan umiddelbart velge de nødvendige feltene uten å bruke hekking. Alt her er ekstremt forenklet for enkel forståelse.

La oss nå se på alt ovenfor ved å bruke et eksempel.
La oss ha en tabell medarbeideravdelinger:

Og vi ønsker å velge fra denne tabellen alle avdelinger der mer enn én ansatt jobber.

SELECT EmployeesDivisions.Division AS Division, NUMBER(EmployeesDivisions.Employee) AS Number ofEmployees FROM EmployeesDivisions AS EmployeesDivisions GROUP BY EmployeesDivisions.Division

Hvis vi kjører denne spørringen, får vi følgende tabell som et resultat

Det andre trinnet er å pålegge en begrensning på antall ansatte på denne tabellen. For å gjøre dette, vil vi gjøre spørringen ovenfor nestet og skrive den tilsvarende betingelsen i den høyere spørringen

SELECT NestedQuery.Unit AS Unit FROM (SELECT EmployeesUnits.Unit AS Unit, QUANTITY(EmployeesUnits.Employee) AS Number OfEmployees FROM EmployeesUnits AS EmployeesUnits GROUP BY EmployeesUnits.Unit) AS NestedQuery WHEREeum NestedQuery WHEREE

Dermed blir resultatet av den endelige spørringen som følger

For å være rettferdig er det verdt å merke seg at det samme resultatet kan oppnås ved å bruke funksjonen HA 1C spørringsspråk, samt bruk av midlertidige tabeller.
I praksis vil du selvsagt støte på mer komplekse nestede spørringer som kan bruke både tabeller og tabeller. Det kan også være flere nivåer av hekking.

Jeg bestemte meg for å gi mitt bidrag og beskrive de funksjonene ved språket som ikke ble diskutert i artiklene ovenfor. Artikkelen er rettet mot nybegynnere.

1. "IZ" design.

For å hente data fra databasen er det slett ikke nødvendig å bruke "FROM"-konstruksjonen.
Eksempel: Vi må velge all informasjon om banker fra bankkatalogen.
Be om:

SELECT Directory.Banks.*

Velger alle felt fra bankkatalogen. Og ligner på forespørselen:

VELG Banker.* FRA Directory.Banks AS Banker

2. Bestilling av data etter referansefelt

Når vi trenger å organisere spørringsdata etter primitive typer: "String", "Number", "Date", etc., så løses alt ved å bruke "ORDER BY"-konstruksjonen hvis du trenger å bestille dataene etter et referansefelt? Referansefeltet er en lenke, en unik identifikator, dvs. Grovt sett kan et vilkårlig sett med tegn og vanlig rekkefølge gi et resultat som ikke er helt forventet. For å bestille referansefelt brukes konstruksjonen "AUTO BESTILLING". For å gjøre dette må du først bestille dataene direkte etter referansetypen ved å bruke "ORDER BY"-konstruksjonen, og deretter "AUTO ORDER"-konstruksjonen.

I dette tilfellet, for dokumenter, vil bestillingen skje i rekkefølgen "Dato->Nummer", for oppslagsverk i "Hovedvisning". Hvis bestillingen ikke skjer etter referansefelt, anbefales det ikke å bruke konstruksjonen "AUTO BESTILLING".

I noen tilfeller kan "AUTO BESTILLING"-konstruksjonen bremse utvelgelsesprosessen. På lignende måte kan du skrive om uten automatisk bestilling av dokumenter:

3.Få en tekstrepresentasjon av en referansetype. "PRESENTASJON" design.

Når du trenger å vise et felt av en referansetype, for eksempel "Bank"-feltet, som er en lenke til et element i "Banks"-katalogen, må du forstå at når du viser dette feltet, vil en underspørring til " Banks"-katalogen vil automatisk bli utført for å få en visning av katalogen. Dette vil redusere datautgangen. For å unngå dette, må du bruke "PREPRESENTATION"-konstruksjonen i forespørselen for umiddelbart å få en representasjon av objektet og deretter vise det for visning.

I datasammensetningssystemet brukes denne mekanismen som standard, men når du lager oppsett i celler, bør du spesifisere representasjonen av referansefeltet, og for eksempel plassere selve lenken i transkripsjonen.

4. Betingelse for prøvetaking av data etter mal.

For eksempel må du få mobiltelefoner til ansatte på skjemaet (8 -123- 456-78-912). For å gjøre dette må du angi følgende betingelse i forespørselen:

VELG Employee.Name, Employee.Phone AS Phone FROM Directory.Employees AS Employees WHERE Phone LIKE "_-___-___-__-__"

Tegnet "_" er et tjenestetegn og erstatter et hvilket som helst tegn.

5. Samtidig bruk av totaler og grupperinger.


Totaler brukes ofte sammen med grupperinger, i dette tilfellet kan det hende at aggregerte funksjoner ikke er spesifisert i totalene.

SELECT Provision of Services.Organization AS Organization, Provision of Services.Nomenclature AS Nomenclature, SUM(Provision of Services.Amount of Document) AS Sum of Document FROM Document.Provision of Services AS Provision of Services GROUP BY Provision of Services.Organisation, Provision of Services.Nomenklatur RESULTATER AV GENERELT, Organisasjon, nomenklatura

I dette tilfellet vil spørringen returnere nesten det samme som følgende spørring:

SELECT Provision of Services.Organization AS Organisation, Provision of Services.Nomenclature AS Nomenclature, Provision of Services.Amount of Document AS Amount of Document FROM Document.Provision of Services AS Provision of Services RESULTATE AMOUNT (Amount of Document) BY GENERAL, Organisation, Nomenklatur

Bare den første spørringen vil skjule poster med samme nomenklatur.

6. Frareferansefelt.

Å referere til felt gjennom en prikk kallesen. For eksempel Betaling.Organisasjon.Administrativ enhet. I dette tilfellet, i referansefeltet "Organisasjon" i "Betaling"-dokumentet, refererer det til en annen tabell "Organisasjoner", der verdien av attributtet "Administrativ enhet" vil bli oppnådd. Det er viktig å forstå at når du får tilgang til felt gjennom en prikk, oppretter plattformen implisitt en underspørring og kobler sammen disse tabellene.

Be om:

Kan representeres som:

VELG Payment.Link, Payment.Organization, Payment.Organization, Organisations. AdministrativeUnit FROM Document.Payment AS Payment VENSTRE JOIN Directory.Organizations AS Organisasjoner Programvare Payment.Organization = Organisasjoner.Link

Når du refererer til referansefelt av en sammensatt type, forsøker rammeverket å lage implisitte sammenføyninger til alle tabeller som er en del av feltets type. I dette tilfellet vil ikke spørringen være optimal Hvis det er klart kjent hvilken type felt det er, er det nødvendig å begrense slike felt etter type med en konstruksjon UTTRYKKE().

For eksempel er det et akkumuleringsregister "Ufordelte betalinger", der flere dokumenter kan fungere som registrar. I dette tilfellet er det feil å innhente verdiene til registrardetaljene på denne måten:

VELG UnallocatedPayments.Register.Date, ..... FROM RegisterAccumulation.UnallocatedPayments AS UnallocatedPayments

du bør begrense typen av det sammensatte feltet til logger:

VELG EXPRESS(UnallocatedPayments.Register AS Document.Payment).Dato, ..... FROM RegisterAccumulation.UnallocatedPayments AS UnallocatedPayments

7. Konstruksjon "HVOR"

Med en venstresammenføyning av to tabeller, når du pålegger en "WHERE"-betingelse på den høyre tabellen, vil vi få et resultat som ligner resultatet med en indre sammenføyning av tabeller.

Eksempel. Det er nødvendig å velge alle klienter fra klientkatalogen og for de klienter som har et betalingsdokument med verdien av attributtet "Organisasjon" = &Organisasjon, vis dokumentet "Betaling", for de som ikke har det, ikke vis det.

Resultatet av spørringen vil returnere poster bare for de klientene som hadde betaling etter organisasjon i parameteren, og vil filtrere ut andre klienter. Derfor må du først motta alle betalinger for "slik og slik" organisasjon i en midlertidig tabell, og deretter koble den til "Kunder"-katalogen ved å bruke en venstre sammenføyning.

VELG Payment.Link AS Payment, Payment.Shareholder AS Client PLASS toPayments FROM Document.Payment AS Payment WHERE Payment.Branch = &Branch; ////////////////////////////////////////////// ////////////////////////// SELECT Clients.Link AS Client, ISNULL(tPayment.Payment, "") AS Betaling FRA Directory .Clients AS Klienter VENSTRE FORBINDELSE topayments SOM topayments SOFTWARE Clients.Link = topayments.Client

Du kan komme deg rundt denne tilstanden på en annen måte. Det er nødvendig å pålegge en "WHERE"-betingelse direkte på forholdet mellom de to tabellene. Eksempel:

VELG Clients.Link, Payment.Link FROM Directory.US_Subscribers AS US_Subscribers VENSTRE CONNECTION Document.Payment AS Payment Software (Clients.Link = Payment.Client AND Payment.Client.Name LIKE "Sugar Packet") GRUPPE ETTER Clients.Link, Payment. Link

8. Blir med nestede og virtuelle tabeller

Nestede søk ofte nødvendig for å hente data basert på en eller annen tilstand. Hvis du deretter bruker dem sammen med andre tabeller, kan dette redusere utførelsen av spørringen kritisk.

For eksempel må vi få saldobeløpet per gjeldende dato for noen klienter.

SELECT UnallocatedPaymentsBalances.Customer, UnallocatedPaymentsBalances.AmountBalance FROM (SELECT Clients.Link AS Link FROM Directory.Clients AS Clients WHERE Clients.Link IN(&Clients)) AS NestedQuery LEFT JOIN RegisterAccumulations.UnallocatedPayments.UnallocatedPayments lokalisertPaymentsBalances. Kunde

Når du utfører en slik spørring, kan DBMS-optimalisatoren gjøre feil når du velger en plan, noe som vil føre til suboptimal utførelse av spørringen. Når du kobler sammen to tabeller, velger DBMS-optimalisatoren en tabellsammenføyningsalgoritme basert på antall poster i begge tabellene. Hvis det er en nestet spørring, er det ekstremt vanskelig å bestemme antall poster som den nestede spørringen vil returnere. Derfor bør du alltid bruke midlertidige tabeller i stedet for nestede spørringer. Så la oss omskrive forespørselen.

SELECT Clients.Link AS Link PLASS tClients FROM Directory.Clients AS Clients WHERE
Clients.Link B (&Clients) ; ////////////////////////////////////////////// //////////////////////////////////// VELG tClients.Link, UnallocatedPaymentsRemains.AmountRemaining, FROM tClients AS tClients LEFT JOIN RegisterAccuulations.UnallocatedPayments.Balances (, Client) IN (SELECT tClients.Link FROM tClients)) AS UnallocatedPaymentsBalances tClients.Link = UnallocatedPaymentsBalances.Clients

I dette tilfellet vil optimizeren kunne bestemme hvor mange poster den midlertidige tabellen tClients bruker og vil kunne velge den optimale algoritmen for å slå sammen tabeller.

Virtuelle bord , lar deg få praktisk talt ferdige data for de fleste anvendte oppgaver (Slice of the First, Slice of the Last, Remains, Turnovers, Remains og Turnovers) Nøkkelordet her er virtuelt. Disse tabellene er ikke fysiske, men kompileres av systemet på farten, dvs. Ved mottak av data fra virtuelle tabeller, samler systemet inn data fra de endelige registertabellene, monterer, grupperer og sender det ut til brukeren.

De. Når du kobler til en virtuell tabell, opprettes en tilkobling til en underspørring. I dette tilfellet kan DBMS-optimalisatoren også velge en ikke-optimal tilkoblingsplan. Hvis spørringen ikke genereres raskt nok og spørringen bruker sammenføyninger i virtuelle tabeller, anbefales det å flytte tilgangen til de virtuelle tabellene til en midlertidig tabell, og deretter lage en sammenføyning mellom to midlertidige tabeller. La oss omskrive den forrige forespørselen.

VELG Clients.Link AS Link PLASSER tClients FROM Directory.Clients AS Clients INDEKS BY Link HVOR
Clients.Link B (&Clients) ; ////////////////////////////////////////////// ///////////////////////////// SELECT ULLOCATEDPAYMENTS.AmountBalance, UnfordoatedPayments.Client as Client Place Balances from RegisterAccumulations.unallocatedPayments.Balances (, klient B ( SELECT tClients Link FROM tClients)) AS UnallocatedPaymentsBalances; ////////////////////////////////////////////// ////////////////////////// SELECT tClients.Link, toRemainders.AmountRemaining AS AmountRemaining FROM tClients AS tClients LEFT JOIN toRemainders AS Remainders BY tClients.Link = tRemainings.Client

9.Sjekker resultatet av forespørselen.

Resultatet av spørringen kan være tomt for å se etter tomme verdier, bruk følgende konstruksjon:

ResRequest = Request.Execute(); Hvis resQuery.Empty() Returner deretter; slutt om;

Metode Tømme() bør brukes før metoder Velge() eller Lesse(), siden det tar tid å hente samlingen.

Det er ikke en åpenbaring for noen at det er ekstremt uønsket å bruke spørringer i en loop. Dette kan kritisk påvirke driftstiden til en bestemt funksjon. Det er svært ønskelig å motta alle dataene i forespørselen og deretter behandle dataene i en loop. Men noen ganger er det tilfeller der det blir umulig å flytte forespørselen utenfor loopen. I dette tilfellet, for optimalisering, kan du flytte opprettelsen av spørringen utenfor loopen, og i loopen erstatte de nødvendige parameterne og utføre spørringen.

Request = Ny forespørsel; Query.Text = "VELG | Clients.Link, | Clients.Birthdate |FROM | Directory.Clients AS Clients |WHERE | Clients.Link = &Client"; For hver rad FRA TableClients Loop Query.SetParameter("Client", Client); QueryResult = Query.Execute().Select(); EndCycle;

Dette vil spare systemet fra syntakskontroll av forespørselen i en løkke.

11. Konstruksjon "HAVING".

Et design som er ganske sjelden i forespørsler. Lar deg pålegge betingelser for verdiene til aggregerte funksjoner (SUM, MINIMUM, AVERAGE, etc.). For eksempel må du bare velge de kundene hvis betalingsbeløp i september var mer enn 13 000 rubler. Hvis du bruker "WHERE"-betingelsen, må du først opprette en midlertidig tabell eller en nestet spørring, gruppere poster der etter betalingsbeløp og deretter bruke betingelsen. "HAVING"-konstruksjonen vil bidra til å unngå dette.

VELG Betaling.Kunde, BELØP(Betaling.Beløp) SOM Beløp FRA Dokument.Betaling SOM Betaling HVOR MÅNED(Betalingsdato) = 9 GRUPPER ETTER Betaling.Kunde HAR BELØP(Betal.Beløp) > 13000

I konstruktøren, for å gjøre dette, går du bare til fanen "Betingelser", legg til en ny tilstand og merker av for "Egendefinert". Så er det bare å skrive Beløp (Betaling.Beløp) > 13000


12. NULL-verdi

Jeg vil ikke her beskrive prinsippene for treverdi-logikk i databasen, det er mange artikler om dette emnet. Bare kort om hvordan NULL kan påvirke resultatet av forespørselen. Verdien NULL er egentlig ikke en verdi, og det faktum at verdien er udefinert er ukjent. Derfor returnerer enhver operasjon med NULL NULL, enten det er addisjon, subtraksjon, divisjon eller sammenligning. En NULL-verdi kan ikke sammenlignes med en NULL-verdi fordi vi ikke vet hva vi skal sammenligne. De. begge disse sammenligningene er: NULL = NULL, NULL<>NULL er ikke sant eller usant, det er ukjent.

La oss se på et eksempel.

For de kundene som ikke har betalinger, må vi vise "Sign"-feltet med verdien "Ingen betalinger". Dessuten vet vi med sikkerhet at vi har slike kunder. Og for å gjenspeile essensen av det jeg skrev ovenfor, la oss gjøre det på denne måten.

VELG "Ingen betalinger" AS Attribut, NULL AS Document PLACE topbetalinger; ////////////////////////////////////////////// //////////////////////////// select clients.link as client, betaling.link hvordan betaling setter tclientpayment fra katalog.clients som klienter forlot tilkoblingsdokumentet. Payment AS Payment Software Clients.Link = Payment.Shareholder; ////////////////////////////////////////////// //////////////////////////// select tclientpayment.client from tclientpayment as tclientpayment internt join tpayment as ttopay by tclientpayment.payment = tpayment

Vær oppmerksom på den andre midlertidige tabellen tClientPayment. Med venstre join velger jeg alle klienter og alle betalinger for disse klientene. For de kundene som ikke har betalinger, vil "Betaling"-feltet være NULL. Etter logikken, i den første midlertidige tabellen "tPayments" utpekte jeg 2 felt, ett av dem NULL, den andre linjen "Har ikke betalinger". I den tredje tabellen kobler jeg sammen tabellene "tClientPayment" og "tPayment" ved å bruke feltene "Payment" og "Document" med en intern sammenføyning. Vi vet at i den første tabellen er «Dokument»-feltet NULL, og i den andre tabellen er de som ikke har betalinger i «Betaling»-feltet også NULL. Hva vil en slik forbindelse returnere til oss? Men det vil ikke returnere noe. Fordi sammenligningen NULL = NULL ikke evalueres til True.

For at forespørselen skal returnere det forventede resultatet, la oss skrive det om:

VELG "Ingen betalinger" AS Attribut, VALUE(Document.Payment.EmptyLink) AS Document PLACE toPayments; ////////////////////////////////////////////// ////////////////////////// SELECT Clients.Link AS Client, ISNULL(Payment.Link, VALUE(Document.Payment.EmptyLink )) HVORDAN Betaling PUT tClientPayment FROM Directory.Clients AS Clients LEFT CONNECTION Document.Payment AS Payment BY Clients.Link = Payment.Shareholder; ////////////////////////////////////////////// //////////////////////////// select tclientpayment.client from tclientpayment as tclientpayment internt join tpayment as ttopay by tclientpayment.payment = tpayment

Nå, i den andre midlertidige tabellen, har vi indikert at hvis "Betaling"-feltet er NULL, så er dette feltet en tom lenke til betalingsdokumentet. I den første tabellen erstattet vi også NULL med en tom referanse. Nå involverer tilkoblingen ikke-NULL-felt og forespørselen vil returnere det forventede resultatet.

Alle forespørsler i artikkelen gjenspeiler situasjonene jeg ønsker å vurdere og ingenting mer. OM De er kanskje ikke vrangforestillinger eller suboptimale, det viktigste er at de gjenspeiler essensen i eksemplet.

13. Et udokumentert trekk ved "CHOICE WHEN...THEN...END"-designet.

I tilfelle det er nødvendig å beskrive "Betingelser"-konstruksjonen i forespørselen, bruker vi standardsyntaksen:

VELG UTVALG NÅR Users.Name = "Vasya Pupkin" SÅ "Vår favorittansatt" ELSE "Vi vet ikke dette" END AS Field1 FROM Directory.Users AS Users

Men hva om vi for eksempel trenger å få månedens navn i en forespørsel? Å skrive en stor konstruksjon i en forespørsel er stygg og tidkrevende, så denne formen for skriving ovenfor kan hjelpe oss:

SELECT MONTH(US_CalculationConsumption_TurnoverSchedule.CalculationPeriod) NÅR 1 SÅ "Januar" NÅR 2 SÅ "FEBRUAR" NÅR 3. SÅ "MARS" NÅR 4. SÅ "April" NÅR 5. SÅ "6. MAI" NÅR JUNI "NÅR JUNI" 8. SÅ "August" NÅR 9. SÅ "September" NÅR 10. SÅ "Oktober" NÅR 11. SÅ

Nå ser designet mindre tungvint ut og er lett å forstå.

14. Batchutførelse av en forespørsel.


For ikke å multiplisere forespørsler kan du lage én stor forespørsel, dele den opp i pakker og jobbe med den.
For eksempel må jeg hente følgende felt fra "Brukere"-katalogen: "Fødselsdato" og de tilgjengelige rollene for hver bruker. last opp dette til ulike tabelldeler på skjemaet. Selvfølgelig kan du gjøre dette i én forespørsel, så må du iterere gjennom postene eller skjule dem, eller du kan gjøre dette:

SELECT Users.Link AS Fullt navn, Users.Fødselsdato, Users.Role PUT vtUsers FROM Directory.Users AS Users; ////////////////////////////////////////////// ////////////////////////// SELECT tueUsers.Full navn, tueUsers.Fødselsdato FROM tueUsers AS tueUsers GROUP BY tueUsers.fullt navn, tueUsers . Fødselsdato; ////////////////////////////////////////////// //////////////////////////// select wusers.full name, wusers.role from wusers as wusers group by wusers.full name, wusers av fødsel

tPackage = Request.ExecutePackage();

TP_BirthDate = tPackage.Upload();
TP_Roles = tPackage.Unload();

Som vi kan se, kan spørringen utføres i en batch og resultatet kan behandles som en matrise. I noen tilfeller er det veldig praktisk.

15. Betingelser i en batchforespørsel

For eksempel har vi en batchforespørsel, hvor vi først får feltene: «Navn, Fødselsdato, Kode» fra «Brukere»-katalogen og ønsker å hente poster med betingelser for disse feltene fra «Individualer»-katalogen.

SELECT Users.Individual.Name AS Name, Users.Individual.Date of Birth AS Fødselsdato, Users.Individual.Code AS Kode PLASS vtUsers FRA Directory.Users AS Users; ////////////////////////////////////////////// /////////////////////////// r r

Du kan stille vilkår som dette:

WHERE Individuals.Code IN (SELECT vtUsers.Code FROM vtUsers) OG Individuals.Name IN (SELECT vtUsers.Code FROM vtUsers) OG Individuals.BirthDate IN (SELECT vtUsers.DateBirth FROM tvUsers)

Og du kan gjøre det slik:

HVOR (Individuals.Code, Individuals.Name, Individuals.Date of Birth) IN (SELECT tueUsers.Code, tueUsers.Name, tueUsers.Date of Birth FROM tueUsers)

Dessuten er det nødvendig å opprettholde orden.

16. Ringe spørringsbyggeren for "tilstand" i en batchforespørsel

Når det er nødvendig å pålegge en betingelse, som i eksemplet ovenfor, kan du glemme hvordan dette eller det feltet kalles i den virtuelle tabellen.
For eksempel må du pålegge en betingelse i "Fødselsdato"-feltet, og i den virtuelle tabellen kalles dette feltet "Debitors fødselsdato", og hvis du glemmer navnet, må du avslutte redigering av betingelsen uten lagre og se på navnet på feltet. For å unngå dette kan du bruke følgende teknikk.

Det er nødvendig å sette parenteser etter konstruksjon "B" og la et tomt mellomrom (mellomrom) mellom parentesene, velg denne plassen og kall opp spørringskonstruktøren. Designeren vil ha tilgang til alle tabellene i batch-spørringen. Teknikken fungerer både på virtuelle registertabeller og på fanen "Betingelser". I sistnevnte tilfelle må du sjekke boksen "P (vilkårlig tilstand)" og gå inn i redigeringsmodusen "F4".

Forespørslene ble ofte gjort på flukt, og de tjener ganske enkelt til å illustrere "teknikkene" som jeg vurderte.

Jeg ønsket å se på bruken av indekser i spørringer, men dette er et veldig bredt tema. Jeg legger det inn i en egen artikkel, eller jeg legger det til her senere.

oppd1. Poeng 11,12
oppd2. Poeng 13,14,15,16

Brukte bøker:
Spørrespråk "1C:Enterprise 8" - E.Yu. Khrustaleva
Faglig utvikling i 1C:Enterprise 8-systemet."

visninger