sql >> Databasteknik >  >> RDS >> Mysql

Avancerad (?) OCH/ELLER fråga

Jag måste säga - jag är stumpad. Jag kan inte komma på någon lösning som skulle komma ens i närheten. Jag skulle försöka leta efter en lösning i dessa riktningar:

  • Användardefinierade aggregatfunktioner. Kanske kan du göra en funktion som tar det önskade uttrycket (i en förenklad syntax) och raderna för en enskild person som argument. Funktionen analyserar sedan uttrycket och matchar det mot raderna. Hmm... kanske MySQL innehåller någon sammanlänkande aggregatfunktion och en matchningsfunktion för regex? Det här kan vara en lösning då (men förmodligen inte särskilt snabb).
  • Analytiska funktioner. Jag låtsas inte att jag förstår dem, men så mycket jag vet om dem tror jag att de generellt är åt det här hållet. Fast jag vet inte om det kommer att finnas en funktion som passar detta behov.

Tillagt: Ahh, jag tror jag fattade det! Även om jag tror att prestationen kommer att bli bedrövlig. Men det här kommer att fungera! Till exempel, om du har kravet att söka efter 1 AND 2 AND (3 OR 4) då skulle du skriva:

SELECT
    *
FROM
    Persons A
WHERE
    EXISTS (Select * from PersonCriteria B WHERE A.PersonID=B.PersonID AND CriteriaID=1)
    AND
    EXISTS (Select * from PersonCriteria B WHERE A.PersonID=B.PersonID AND CriteriaID=2)
    AND
    (
        EXISTS (Select * from PersonCriteria B WHERE A.PersonID=B.PersonID AND CriteriaID=3)
        OR
        EXISTS (Select * from PersonCriteria B WHERE A.PersonID=B.PersonID AND CriteriaID=4)
    )

Lägg till 2: Här är en till, även om prestandan troligen kommer att bli ännu sämre:

SELECT p.* FROM Person p
    JOIN (select PersonID from PersonCriteria WHERE CriteriaID=1) c1 ON p.PersonID=c1.PersonID
    JOIN (select PersonID from PersonCriteria WHERE CriteriaID=2) c2 ON p.PersonID=c2.PersonID
    JOIN (select PersonID from PersonCriteria WHERE CriteriaID IN (3,4)) c3 ON p.PersonID=c3.PersonID

3 har lagts till: Det här är en variant av nr 2, men det här kan faktiskt ha en chans till en anständig prestation!

SELECT p.* FROM
    Person p
    JOIN PersonCriteria c1 on (p.PersonID=c1.PersonID AND c1.CriteriaID=1)
    JOIN PersonCriteria c2 on (p.PersonID=c2.PersonID AND c2.CriteriaID=2)
    JOIN PersonCriteria c3 on (p.PersonID=c3.PersonID AND c3.CriteriaID IN (3,4))

Om du lägger till ett index till PersonCriteria på kolumner (PersonID,CriteriaID) (exakt i denna ordning!), så tror jag att det går ungefär lika snabbt som du kommer att få i alla fall.



  1. PHP-varning:mysqli_connect():(HY000/2002):Anslutning nekad

  2. Topp 30 mest användbara Concurrent Manager-frågor

  3. Hur skapar man LEFT JOIN med SELECT-underfrågan med QueryBuilder i Doctrine 2?

  4. Hur får man lediga datum med reservationer?