sql >> Database teknologi >  >> RDS >> Database

Sådan skriver du komplekse forespørgsler i SQL

Typiske forespørgsler i tabelformatet SELECT * FROM er nogle gange ikke nok. Når dataene for en forespørgsel ikke er i én tabel, men i flere, eller når det er nødvendigt at angive flere udvælgelsesparametre på én gang, har du brug for mere sofistikerede forespørgsler.

Denne artikel vil forklare, hvordan man opbygger sådanne forespørgsler og giver eksempler på komplekse SQL-forespørgsler.

Hvordan ser en kompleks forespørgsel ud?

Lad os først definere betingelserne for at sammensætte SQL-forespørgslen. Du skal især bruge følgende valgparametre:

  • navnene på de tabeller, som du vil udtrække data fra;
  • værdierne af felter, der skal returneres til de oprindelige efter ændringer i databasen;
  • relationerne mellem tabeller;
  • prøveudtagningsbetingelserne;
  • hjælpeudvælgelseskriterierne (begrænsninger, måder at præsentere information på, type sortering).

For bedre at forstå emnet, lad os overveje et eksempel, der bruger de følgende fire enkle tabeller. Den første linje er navnet på den tabel, der i komplekse forespørgsler fungerer som en fremmednøgle. Vi vil overveje dette nærmere med et eksempel:

Hver tabel har rækker relateret til nogle andre tabeller. Vi forklarer, hvorfor det er nødvendigt yderligere.

Lad os nu se på den grundlæggende SQL-forespørgsel:

SELECT * FROM companies WHERE companies_name %STARTSWITH 'P';

%STARTSWITH prædikat vælger rækker, der begynder med det eller de angivne tegn.

Resultatet ser således ud:

Lad os nu overveje en kompleks SQL-forespørgsel:

SELECT 
	companies.companies_name,
	SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
	AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY 
	companies.id,
	companies.companies_name
HAVING AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls)
ORDER BY calls DESC, companies.id ASC;

Resultatet er følgende tabel:

Tabellen viser virksomhederne, det tilsvarende antal telefonopkald og deres omtrentlige varighed.

Ydermere viser den kun de firmanavne, hvor den gennemsnitlige opkaldsvarighed er længere end den gennemsnitlige opkaldsvarighed i andre virksomheder.

Hvad er hovedreglerne for oprettelse af kompleks SQL-forespørgsel?

Lad os prøve at skabe en multifunktionel algoritme til at komponere komplekse forespørgsler.

Først og fremmest skal du beslutte dig for de tabeller, der består af de data, der deltager i forespørgslen.

Eksemplet ovenfor involverer virksomhederne og opkald tabeller. Hvis tabellerne med de nødvendige data ikke er direkte relateret til hinanden, skal du også inkludere de mellemliggende tabeller, der forbinder dem.

Af denne grund forbinder vi også tabeller, såsom kontorer og kunder , ved hjælp af fremmednøgler. Derfor vil ethvert resultat af forespørgslen med tabeller fra dette eksempel altid inkludere nedenstående linjer:

SELECT 
	...
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
...;

After that, you must test the correctness of the behavior in the following part of the query:

SELECT * FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id;

En kombineret tabel foreslår de tre vigtigste punkter:

  • Vær opmærksom på listen over felter efter SELECT. Operationen med at læse data fra sammenføjede tabeller kræver, at du angiver navnet på tabellen, der skal sammenføjes i navnet felt.
  • Din komplekse forespørgsel vil altid have hovedtabellen (virksomheder ). De fleste af felterne læses fra den. Den vedhæftede tabel, i vores eksempel, bruger tre tabeller – kontorer , kunder , og opkald . Navnet bestemmes efter JOIN-operatøren.
  • Ud over at angive navnet på den anden tabel, skal du sørge for at angive betingelsen for at udføre sammenkædningen. Vi vil diskutere denne betingelse yderligere.
  • Forespørgslen viser en tabel med et stort antal rækker. Det er ikke nødvendigt at offentliggøre det her, da det viser mellemresultater. Du kan dog altid selv kontrollere outputtet. Dette er meget vigtigt, da det hjælper med at undgå fejl i det endelige resultat.

Lad os nu se på den del af forespørgslen, der sammenligner opkaldsvarigheder inden for hver virksomhed og mellem alle virksomheder. Vi skal beregne den gennemsnitlige varighed af alle opkald. Brug følgende forespørgsel:

SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls

Bemærk, at vi brugte DATEDIFF funktion, som udsender forskellen mellem de angivne perioder. I vores tilfælde er den gennemsnitlige opkaldsvarighed lig med 335 sekunder.

Lad os nu tilføje data om opkald fra alle virksomheder til forespørgslen.

SELECT 
	companies.companies_name,
	SUM(CASE WHEN calls.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
	AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY 
	companies.id,
	companies.companies_name
ORDER BY calls DESC, companies.id ASC;

I denne forespørgsel,

  • SUM (CASE NÅR calls.id IKKE ER NULL SÅ 1 ANDEN 0 END) – for at undgå unødvendige operationer opsummerer vi kun eksisterende opkald – når antallet af opkald i en virksomhed ikke er nul. Dette er meget vigtigt i store tabeller med mulige nulværdier.
  • AVG (ISNULL (DATEDIFF (SECOND, calls.start_time, calls.end_time), 0)) – forespørgslen er identisk med AVG-forespørgslen ovenfor. Men her bruger vi ISNULL operatør, som erstatter NULL med 0. Det er nødvendigt for virksomheder uden opkald overhovedet.

Vores resultater:

Vi er næsten færdige. Ovenstående tabel viser listen over virksomheder, det tilsvarende antal opkald for hver af dem og den gennemsnitlige opkaldsvarighed i hver af dem.

Det eneste, der er tilbage, er at sammenligne tallene fra den sidste kolonne med den gennemsnitlige varighed af alle opkald fra alle selskaber (335 sekunder).

Hvis du indtaster den forespørgsel, som vi præsenterede helt i begyndelsen, skal du blot tilføje HAV del, får du det, du har brug for.

Vi anbefaler kraftigt at tilføje kommentarer på hver linje, så du ikke bliver forvirret i fremtiden, når du skal rette nogle eksisterende komplekse SQL-forespørgsler.

Sidste tanker

Selvom hver kompleks SQL-forespørgsel kræver en individuel tilgang, er nogle anbefalinger velegnede til forberedelsen af ​​de fleste sådanne forespørgsler.

  • bestem, hvilke tabeller der skal deltage i forespørgslen;
  • opret komplekse forespørgsler fra enklere dele;
  • kontroller nøjagtigheden af ​​forespørgsler sekventielt, i dele;
  • test nøjagtigheden af ​​din forespørgsel med mindre tabeller;
  • skriv detaljerede kommentarer på hver linje, der indeholder operanden, ved hjælp af symbolerne '-'.

Specialiserede værktøjer gør dette arbejde meget mere ligetil. Blandt dem vil vi anbefale at bruge Query Builder - et visuelt værktøj, der gør det muligt at konstruere selv de mest komplekse forespørgsler meget hurtigere i en visuel tilstand. Dette værktøj er tilgængeligt som en selvstændig løsning eller som en del af det multifunktionelle dbForge Studio til SQL Server.

Vi håber, at denne artikel har hjulpet dig med at afklare dette specifikke problem.


  1. Fejl ved installation af pg gem, mkmf.rb kan ikke finde header-filer til ruby ​​(Mac OSX 10.6.5)

  2. Sådan gemmer du Emoji-karakterer i MySQL-databasen

  3. En tilgang til indeksjustering – del 2

  4. Sådan laver du en inventardatabase i Microsoft Access