简体   繁体   中英

Oracle find record by multiple matching criteria

I'm trying to find records by multiple matching values in two columns.

Just to give you an example on what I'm trying to do: I have a form which is saved in the database and contains checkboxes about a sickness, which can or cannot be present when a patient is admissioned in the hospital.

These are like:

Acquistion Time: Admission [ ]  Follow-Up [ ]  Transfer [ ]  Discharge [ ]
Illness present? Yes [ ]  No [ ]

So patients can have multiple of those surveys.

Now what I'm trying to do: I have to find patients where the illness WAS NOT present when they entered the hospital ( combination of Admission and No ) BUT evolved during their stay ( combination of Follow-Up and Yes )

My idea was to go with two EXISTS statements, but it didn't work out (+ the runtime is really long):

EDIT :

The dataset I have right now (I didn't add the whole query at first) looks like this (limited to one case to make it readable):

CaseNumber CaseID Admission Date Acquisition Date Flag Checkbox
123456789 123 09.11.2020 13.11.2020 16:13 1 cbxAdmission
123456789 123 09.11.2020 13.11.2020 16:13 0 cbxFollowUp
123456789 123 09.11.2020 13.11.2020 16:13 0 cbxIllnessPresent
123456789 123 09.11.2020 13.12.2020 10:23 0 cbxAdmission
123456789 123 09.11.2020 13.12.2020 10:23 1 cbxFollowUp
123456789 123 09.11.2020 13.12.2020 10:23 1 cbxIllnessPresent
123456789 123 09.11.2020 20.11.2020 07:38 0 cbxAdmission
123456789 123 09.11.2020 20.11.2020 07:38 1 cbxFollowUp
123456789 123 09.11.2020 20.11.2020 07:38 0 cbxIllnessPresent

This is the according query:

SELECT DISTINCT
    f.FALLNR AS "Fall",
    f.FALLID,
    TO_CHAR(f.AUFNDAT, 'DD.MM.YYYY') AS "Aufnahmedatum",
    --cf.TEXT AS "Text",
    CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) AS "Befundzeitpunkt",
    --cp.PRIMITIVUMNUMMER,
    --ck.NUMMER,
    cf2.FLAG,
    --cf2.WERT,
    cf3.CODE
FROM
    OS_CW.CW_PRIMITIVUM cp 
    INNER JOIN FALL f ON f.FALLID = cp.FALL
    INNER JOIN OS_CW.CW_KLASSE ck ON ck.NUMMER = cp.KLASSE
    LEFT JOIN OS_CW.CW_FELDTEXT cf ON cf.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
    LEFT JOIN OS_CW.CW_FELDDATEN cf2 ON cf2.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
    LEFT JOIN OS_CW.CW_FELDCODE cf3 ON cf3.NUMMER = cf2.FELDDEFINITION 
WHERE
    ck.MAPPENNUMMER = 16
    AND f.FALLNR = 123456789
    AND f.MEDICALCASESTATE IN (65366, 65369)
    AND f.CASEMARK IN (38140, 38142)
    AND EXTRACT(YEAR FROM f.ENTLDAT) = 2021
    AND cp.STORNIERT = 0
    AND (cf3.CODE = 'cbxAdmission' OR cf3.CODE = 'cbxFollowUp' OR cf3.CODE = 'cbxIllnessPresent')
GROUP BY f.FALLNR, f.FALLID, CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')), TO_CHAR(f.AUFNDAT, 'DD.MM.YYYY'), cf2.FLAG, cf3.CODE
ORDER BY CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')), cf3.CODE DESC

Now I need a query that returns the CaseNumber and the acquistion date if the criteria I already described matches - which should be the case here because it wasn't present on admission / first acquisition (13.11.2021) but it then it evolved and was present on the next acquistion (13.12.2021), which is a follow-up.

I thought of analytical functions but couldn't find one which fits my needs (I'm not the most experienced person in Oracle DBMS).

Any ideas if (and if yes - how) this could be turned into a query?

Thanks for any helpful anwers!

I think you can combine those with or in last condition as below:

AND EXISTS (
    SELECT *
    FROM OS_CW.CW_PRIMITIVUM cp2 
    JOIN OS_CW.CW_FELDTEXT cf4 ON cf4.PRIMITIVUMNUMMER = cp2.PRIMITIVUMNUMMER
    JOIN OS_CW.CW_FELDDATEN cf5 ON cf5.PRIMITIVUMNUMMER = cp2.PRIMITIVUMNUMMER
    JOIN OS_CW.CW_FELDCODE cf6 ON cf6.NUMMER = cf5.FELDDEFINITION 
    WHERE cp2.FALL = f.FALLID
    AND (((cf6.CODE = 'cbxAdmission' AND cf5.FLAG = 1) AND (cf6.CODE = 'cbxIllnessPresent' AND cf5.FLAG = 0))
    or ((cf6.CODE = 'cbxFollowUp' AND cf5.FLAG = 1) AND (cf6.CODE = 'cbxIllnessPresent' AND cf5.FLAG = 1)))

Okay, after some trial and error and logical thinking about it I managed to put a working query together, I just used INNER JOIN to always combine the matching criteria between the different tables.

The final result looks like this (don't mind the German descriptions etc.)

 SELECT 
"Fall", 
"Vorname",
"Name",
"Geburtsdatum",
"Aufnahmedatum", 
"Befundzeitpunkt Aufnahme", 
"Erhebungart A", 
"Dekubitus vorh. b. Aufn." ,
"Befundzeitpunkte Folgeerhebungen",
"Erhebungsart F",
"Dekubitus vorh. b. Folgeerh."
FROM (
    SELECT DISTINCT 
        t1."Fall", 
        t1."Vorname",
        t1."Name",
        t1."Geburtsdatum",
        t1."Aufnahmedatum", 
        t1."Befundzeitpunkt Aufnahme", 
        t1."Erhebungsart" AS "Erhebungart A",
        t2."Flag" AS "Dekubitus vorh. b. Aufn.",
        LISTAGG(t3."Befundzeitpunkt Folgeerhebung", ', ') WITHIN GROUP (ORDER BY t3."Befundzeitpunkt Folgeerhebung") OVER (PARTITION BY t1."Fall") AS "Befundzeitpunkte Folgeerhebungen",
        t3."Erhebungsart" AS "Erhebungsart F",
        t4."Flag" AS "Dekubitus vorh. b. Folgeerh."
    FROM
        /* Checkbox "Dekubituserhebung zur Aufnahme" = TRUE */
        (SELECT DISTINCT
            f.FALLNR AS "Fall",
            np.VORNAME AS "Vorname",
            np.NAME AS "Name",
            TO_CHAR(np.GEBDAT, 'DD.MM.YYYY') AS "Geburtsdatum",
            TO_CHAR(f.AUFNDAT, 'DD.MM.YYYY') AS "Aufnahmedatum",
            CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) AS "Befundzeitpunkt Aufnahme",
            DECODE(cf2.FLAG, 0, 'Nein', 1, 'Ja') AS "Flag",
            DECODE(cf3.CODE, 'cbxDekuZurAufnahme', 'Ersterhebung') AS "Erhebungsart"
        FROM 
            OS_CW.CW_PRIMITIVUM cp 
            INNER JOIN FALL f ON f.FALLID = cp.FALL
            INNER JOIN NATPERSON np ON f.PERSNR = np.PERSNR
            INNER JOIN OS_CW.CW_KLASSE ck ON ck.NUMMER = cp.KLASSE
            LEFT JOIN OS_CW.CW_FELDTEXT cf ON cf.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDDATEN cf2 ON cf2.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDCODE cf3 ON cf3.NUMMER = cf2.FELDDEFINITION 
        WHERE
            ck.MAPPENNUMMER = 16
            AND f.MEDICALCASESTATE IN (65366, 65369)
            AND f.CASEMARK IN (38140, 38142)
            AND EXTRACT(YEAR FROM f.ENTLDAT) = 2021
            AND cp.STORNIERT = 0
            AND (cf3.CODE = 'cbxDekuZurAufnahme' AND cf2.FLAG = 1)
        ) t1
    
        INNER JOIN 
        
        /* Checkbox "Dekubituserhebung zur Aufnahme" = TRUE UND Checkbox "Dekubitus vorhanden" = FALSE - kein Dekubitus bei Aufnahmeerehbung */
        (SELECT DISTINCT
            f.FALLNR AS "Fall",
            CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) AS "Befundzeitpunkt Aufnahme",
            DECODE(cf2.FLAG, 0, 'Nein', 1, 'Ja') AS "Flag",
            DECODE(cf3.CODE, 'cbxDekubitusVorhanden', 'Dekubitus vorhanden') AS "Dekubitus vorhanden"
        FROM 
            OS_CW.CW_PRIMITIVUM cp 
            INNER JOIN FALL f ON f.FALLID = cp.FALL
            INNER JOIN OS_CW.CW_KLASSE ck ON ck.NUMMER = cp.KLASSE
            LEFT JOIN OS_CW.CW_FELDTEXT cf ON cf.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDDATEN cf2 ON cf2.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDCODE cf3 ON cf3.NUMMER = cf2.FELDDEFINITION 
        WHERE
            ck.MAPPENNUMMER = 16
            AND f.MEDICALCASESTATE IN (65366, 65369)
            AND f.CASEMARK IN (38140, 38142)
            AND EXTRACT(YEAR FROM f.ENTLDAT) = 2021
            AND cp.STORNIERT = 0
            AND (cf3.CODE = 'cbxDekubitusVorhanden' AND cf2.FLAG = 0)
        ) t2
        
        ON t1."Fall" = t2."Fall"
        AND t1."Befundzeitpunkt Aufnahme" = t2."Befundzeitpunkt Aufnahme"
        
        INNER JOIN
        
        /* Checkbox "Dekubituserhebung als Folgeerhebung" = TRUE */
        (SELECT DISTINCT
            f.FALLNR AS "Fall",
            CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) AS "Befundzeitpunkt Folgeerhebung",
            DECODE(cf2.FLAG, 0, 'Nein', 1, 'Ja') AS "Flag",
            DECODE(cf3.CODE, 'cbxDekuFolgeerhebung', 'Folgeerhebung') AS "Erhebungsart"
        FROM 
            OS_CW.CW_PRIMITIVUM cp 
            INNER JOIN FALL f ON f.FALLID = cp.FALL
            INNER JOIN OS_CW.CW_KLASSE ck ON ck.NUMMER = cp.KLASSE
            LEFT JOIN OS_CW.CW_FELDTEXT cf ON cf.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDDATEN cf2 ON cf2.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDCODE cf3 ON cf3.NUMMER = cf2.FELDDEFINITION 
        WHERE
            ck.MAPPENNUMMER = 16
            AND f.MEDICALCASESTATE IN (65366, 65369)
            AND f.CASEMARK IN (38140, 38142)
            AND EXTRACT(YEAR FROM f.ENTLDAT) = 2021
            AND cp.STORNIERT = 0
            AND (cf3.CODE = 'cbxDekuFolgeerhebung' AND cf2.FLAG = 1)
        ) t3
        
        ON t1."Fall" = t3."Fall"
        AND t2."Fall" = t3."Fall"
        
        INNER JOIN 
        
        /* Checkbox "Dekubituserhebung als Folgeerhebung" = TRUE UND Checkbox "Dekubitus vorhanden" = TRUE - Dekubitus während Aufenthalt entwickelt */
        (SELECT DISTINCT
            f.FALLNR AS "Fall",
            CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) AS "Befundzeitpunkt Folgeerhebung",
            DECODE(cf2.FLAG, 0, 'Nein', 1, 'Ja') AS "Flag",
            DECODE(cf3.CODE, 'cbxDekubitusVorhanden', 'Dekubitus vorhanden') AS "Dekubitus vorhanden"
        FROM 
            OS_CW.CW_PRIMITIVUM cp 
            INNER JOIN FALL f ON f.FALLID = cp.FALL
            INNER JOIN OS_CW.CW_KLASSE ck ON ck.NUMMER = cp.KLASSE
            LEFT JOIN OS_CW.CW_FELDTEXT cf ON cf.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDDATEN cf2 ON cf2.PRIMITIVUMNUMMER = cp.PRIMITIVUMNUMMER
            LEFT JOIN OS_CW.CW_FELDCODE cf3 ON cf3.NUMMER = cf2.FELDDEFINITION 
        WHERE
            ck.MAPPENNUMMER = 16
            AND f.MEDICALCASESTATE IN (65366, 65369)
            AND f.CASEMARK IN (38140, 38142)
            AND EXTRACT(YEAR FROM f.ENTLDAT) = 2021
            AND cp.STORNIERT = 0
            --AND CONCAT(CONCAT(TO_CHAR(cp.MEDDATE, 'DD.MM.YYYY'), ' '), TO_CHAR(cp.MEDTIME, 'HH24:MI')) = '16.09.2020 16:47'
            AND (cf3.CODE = 'cbxDekubitusVorhanden' AND cf2.FLAG = 1)
        ) t4    
        
        ON t3."Befundzeitpunkt Folgeerhebung" = t4."Befundzeitpunkt Folgeerhebung"
        AND t3."Fall" = t4."Fall"
)
ORDER BY "Aufnahmedatum", "Fall", TO_DATE("Befundzeitpunkt Aufnahme", 'DD.MM.YYYY HH24:MI')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM