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

forespørgsel efter et sæt i en relationsdatabase

Jeg vil ikke kommentere på, om der er et bedre egnet skema til at gøre dette (det er meget muligt), men for et skema med kolonner name og item , bør følgende forespørgsel fungere. (mysql-syntaks)

SELECT k.name
FROM (SELECT DISTINCT name FROM sets) AS k
INNER JOIN sets i1 ON (k.name = i1.name AND i1.item = 1)
INNER JOIN sets i2 ON (k.name = i2.name AND i2.item = 3)
INNER JOIN sets i3 ON (k.name = i3.name AND i3.item = 5)
LEFT JOIN sets ix ON (k.name = ix.name AND ix.item NOT IN (1, 3, 5))
WHERE ix.name IS NULL;
 

Ideen er, at vi har alle de indstillede nøgler i k , som vi så forbinder med de indstillede varedata i sets én gang for hvert sæt i det sæt, vi søger efter, tre i dette tilfælde. Hver af de tre indre joinforbindelser med tabelaliasser i1 , i2 og i3 filtrere alle sætnavne fra, der ikke indeholder det element, der blev søgt efter med det pågældende join. Endelig har vi en venstre join med sets med tabelalias ix , som bringer alle de ekstra varer ind i sættet, det vil sige alle de ting, vi ikke ledte efter. ix.name er NULL i tilfælde af, at der ikke findes ekstra genstande, hvilket er præcis det, vi ønsker, således WHERE klausul. Forespørgslen returnerer en række, der indeholder sætnøglen, hvis sættet findes, ellers ingen rækker.

Rediger: Ideen bag collapsars svar ser ud til at være meget bedre end mit, så her er en lidt kortere version af det med forklaring.

SELECT sets.name
FROM sets
LEFT JOIN (
    SELECT DISTINCT name
    FROM sets
    WHERE item NOT IN (1, 3, 5)
) s1
ON (sets.name = s1.name)
WHERE s1.name IS NULL
GROUP BY sets.name
HAVING COUNT(sets.item) = 3;
 

Ideen her er, at underforespørgsel s1 vælger nøglerne for alle sæt, der indeholder andre elementer end dem, vi leder efter. Så da vi forlod join sets med s1 , s1.name er NULL når sættet kun indeholder elementer, vi søger efter. Vi grupperer derefter efter sætnøgle og filtrerer alle sæt fra med det forkerte antal varer. Vi står så tilbage med kun sæt, som kun indeholder varer, vi søger efter, og som har den rigtige længde. Da sæt kun kan indeholde et element én gang, kan der kun være ét sæt, der opfylder disse kriterier, og det er det, vi leder efter.

Rediger: Det gik lige op for mig, hvordan man gør dette uden udelukkelsen.

SELECT totals.name FROM ( SELECT name, COUNT(*) count FROM sets GROUP BY name ) totals INNER JOIN ( SELECT name, COUNT(*) count FROM sets WHERE item IN (1, 3, 5) GROUP BY name ) matches ON (totals.name = matches.name) WHERE totals.count = 3 AND matches.count = 3;

Den første underforespørgsel finder det samlede antal elementer i hvert sæt, og den anden finder ud af antallet af matchende elementer i hvert sæt. Når matches.count er 3, har sættet alle de varer, vi leder efter, og hvis totals.count er også 3, har sættet ingen ekstra genstande.



  1. mysql_connect() mislykkes med tom advarsel

  2. Tilføj en beregnet kolonne til en eksisterende tabel i SQL Server

  3. Sådan opretter du et sikkert login-script i PHP og MySQL

  4. Microsoft OLE DB uudviklet! Længe leve ADO!