简体   繁体   中英

Union query to combine results of 3 tables

I am relatively new to coding so please have patience.

I am trying to combine data from 3 tables. I have managed to get some data back but it isn't what i need. Please see my example below.

select oid, rrnhs, idnam, idfnam, dte1, ta  
  as 'access type' from person
left join 
  (select fk_oid, min(dte), dte1, ta
   from 
     ((Select fk_oid,min(accessdate) as dte, accessdate1 as dte1, accesstype as ta 
        from vascularpdaccess 
        where isnull(accesstype)=false group by fk_oid)
union
 (Select fk_oid, min(hpdate) as dte, hpdate as dte1, HPACCE as ta 
   from hdtreatment 
   where isnull(hptype)=false group by fk_oid)) as bla
 group by fk_oid) as access
 on person.oid=access.fk_oid
 where person.rrnhs in (1000010000, 2000020000, 3000030000)

My understanding with a union is that the columns have to be of the same data type but i have two problems. The first is that accesstype and hpacce combine in to a the same column as expected, but i dont want to actually see the hpacce data (dont know if this is even possible). Secondly, the idea of the query is to pull back a patients 'accesstype' date at the first date of hpdate .

I dont know if this even makes sens to you guys but hoping someone can help..y'all are usually pretty nifty!

Thanks in advance!

Mikey

All queries need to have the same number of columns in the SELECT statement. It looks like you first query has the max number of columns, so you will need to "pad" the other to have the same number of columns. You can use NULL as col to create the column with all null values.

To answer the question (I think) you were asking... for a UNION or UNION ALL set operation, you are correct: the number of columns and the datatypes of the columns returned must match.

But it is possible to return a literal as an expression in the SELECT list. For example, if you don't want to return the value of HPACCE column, you can replace that with a literal or a NULL. (If that column is character datatype (we can't tell from the information provided in the question), you could use (for example) a literal empty string '' AS ta in place of HPACCE AS ta .

                     SELECT fk_oid
                          , MIN(HPDATE)   AS dte
                          , hpdate        AS dte1
                          , NULL          AS ta
    -- -------------------- ^^^^
                       FROM hdtreatment

Some other notes:

The predicate ISNULL(foo)=FALSE can be more simply expressed as foo IS NOT NULL .

The UNION set operator will remove duplicate rows. If that's not necessary, you could use a UNION ALL set operator.

The subsequent GROUP BY fk_oid operation on the inline view bla is going to collapse rows; but it's indeterminate which row the values from dte1 and ta will be from. (ie there is no guarantee those values will be from the row that had the "minimum" value of dte .) Other databases will throw an exception/error with this statement, along the lines of "non-aggregate in SELECT list not in GROUP BY". But this is allowed (without error or warning) by a MySQL specific extension to GROUP BY behavior. (We can get MySQL to behave like other databases and throw an error of we specify a value for sql_mode that includes ONLY_FULL_GROUP_BY (?).)

The predicate on the outer query doesn't get pushed down into the inline view bla . The view bla is going to materialized for every fk_oid , and that could be a performance issue on large sets.

Also, qualifying all column references would make the statement easier to read. And, that will also insulate the statement from throwing an "ambiguous column" error in the future, when a column named (eg) ta or dte1 is added to the person table.

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