SAS SQL JOIN increase rows instead of match rows - sql

I have a problem with full outer join in SAS
I want to join two database.
A is the "mama" containing patient ID,SEX,RACE,blablabla...but dont have the status variable.
B is the one only containing ID and status.
So A is actually a way bigger database than B and what I'm going to do is to put B including status into A. Here's my code:
proc sql;
CREATE TABLE C AS
select *
from A full outer join B
on A.id=B.id ;
RUN;
The result I got is actually not merging two database. Instead, I got the database C, which all the data from A on the top(status variable is null), and then the data B following by A (status variable is there but all other variables are showing Null). Thus, what i did is just adding rows....
Here is some conditions on my codes;
1. I use the University Edition
2. the format of ID is actually Char. Since B's ID (example:BD123), I convert numeric variable ID from A into char variable .
Anybody could help me with this? Thank you very much :-D

If you got an entire concatenation (100 rows in A, 15 rows in B, 115 in C) then you likely didn't correctly match the ID variable format when you converted. You may have an issue with additional spaces or something to that effect (the length of B.id may not match A.id). If possible I would convert the ID to numeric, or do a more careful conversion to character.
Second, if you're intending to just get the number of rows of A back (just adding B information to A), then you want a left join not a full outer join.

I Think you might be looking at left join instead.
proc sql;
create table C as
select A.*, B.*
from A left join B
on A.ID=B.ID;
quit;

Related

Values after join are incorrect

I have 2 database tables. Table A has to fetch some records based on parameter passed there may or may not be an entry in table B with that key.
What I want to do is:
select a.col1,a.col2,a.col3
FROM table WHERE a.id = 123
This would fetch 20 rows. For one of the rows there is an entry in another table B.
select T_level from table b where b.id = 123
only one record appears with right value.
What I want is to get this in a single query. Something like:
select a.col1,a.col2,a.col3,b.T_level
from a,b
where a.id = 123
and a.id = b.id
When I do that, I get 20 rows and the column T_level as '50' for all the rows, whereas it should be '50' for one correct row, for rest it should be null.
I further tried:
select a.col1,a.col2,a.col3,nvl(b.T_level,0) from a,b
but that doesn't fetch the way I expect.
Firstly, please learn to use ansi sql join syntax. The Oracle join syntax you are using hasn't been considered good practice for decades
SQL Join syntax
If you want to get all records from a and any matching records from b then you need to use a LEFT OUTER JOIN

Convert columnB value if columnA = X in SQL

Overview
I have an inner join statement that links 5 tables together which is working fantastically if i do say so myself.
Now one of the values returned is in Hex and it is in a column named Value however, the Value column also contains other values and so i cannot simply convert the whole column.
Every Hex entry into column Value has an identifier of 18 in a column called DataTypeID.
The Question
How can i convert just the Hex entry in column Value if DataTypeID=18.
I know this needs a function with:
SELECT CONVERT(INT, CONVERT(VARBINARY
But I am unsure of how to write it and where to place it, is it before my inner join statement or after?
SELECT Data.Value AS Value, Entry_Data.DataTypeID AS DataTypeID
From Database.Entry
INNER JOIN Database.Data on Entry_Data.DataTypeID=DataTypeID
INNER Join Database.Data on Data.Value=Value
Please note that this is not an accurate example of the script its just for example purposes
Now i assume that i would create my function above this query and then add a where function below it.
The names of the columns and identifier are accurate.
You can use the case expression.
Your query is a little difficult to interpret intent, so I am going to make an assumption that you have two tables, (TableA and TableB) and you want to join one to the other like this: TableA.Value = TableB.Value, but TableB stores its Value column as a mixture of ints and hex(ints) where the hex(insts) are identified by value of TableB.VDataTypeID = 18 and anyt other DataTypeID indicates that TableB.Value a regular int.
If this is the case, to the following:
SELECT
...
FROM
TableA
INNER JOIN TableB ON TableA.Value
= CASE WHEN TableB.DataTypeID = 18 THEN Convert(...
ELSE TableB.DataTypeID
END
So you are using the CASE expression effectively as an in-place function on which to join.
It reads, Join TableA to TableB on the Values directly if TableB.DataTypeID is not 18, but if it is 18, then convert TableB.Value first and then do the join.
Hope this gives you what you need :-)

How to populate query with result from different table?

I have two tables. Table A and table B. Table A has a column that is a reference to the primary key to table B. I want to run a select query on table A and then populate the column that referrers to B with all of the data in that row of B.
SELECT * from A a LEFT JOIN B b ON a."b_id" = b."id" WHERE ...
That gives a result with each row containing all of the columns of A and all of the columns of B. It is a confusing mess to figure out which column is from which table. I want to be able to do something like.
row.A."column name"
row.B."column name"
I don't want to have to rename every single column using AS. There must be a better way to do this.
Not a 100% sure what your asking but what I think your asking is.
You want a way to have only column B values to show? If so you could do:
SELECT B.*
FROM A
JOIN B
ON A.b_id = B.id
That will only get you the B columns and data, If you want A also maybe do but you want to have it separate from b maybe do:
SELECT B.*,'|' AS ['|'], A.*
FROM A
JOIN B
ON A.b_id = B.id
Hopefully this is helpful, if not to you maybe another reader.

Column in field list is ambiguous error

i've been recently working in mysql and in one of the requests i wrote :
SELECT SIGLE_EEP, ID_SOUS_MODULE, LIBELLE
FROM mef_edi.eep a, mef_edi.envoi e, mef_edi.sous_module s
WHERE a.ID_EEP = e.ID_EEP
AND a.ID_SOUS_MODULE = s.ID_SOUS_MODULE;
and they told me :
Column ID_SOUS_MODULE in field list is ambiguous
What should i do ?
More than one table has a column named ID_SOUS_MODULE.
So you need to name the table every time you mention the column to specify which table you mean.
Change
SELECT ID_SOUS_MODULE
for instance to
SELECT a.ID_SOUS_MODULE
I agree with the answer above, you may have duplicate column names across your 3 tables, assigning the table id (a, e, s) as noted above will avoid that issue in the select. In addition to what #juergen said you may want to get rid of that cartesian join by using an inner or left join (inner seems to be what your going for). The way you are joining your table you are joining every possible combination of rows together than filtering. using a proper join will get you better performance in the long run as your table line counts grow. Here is an example of a non cartesian join:
SELECT SIGLE_EEP, ID_SOUS_MODULE, LIBELLE
FROM mef_edi.eep a
INNER JOIN mef_edi.envoi e ON (a.ID_EEP = e.ID_EEP)
INNER JOIN mef_edi.sous_module s ON (a.ID_SOUS_MODULE = s.ID_SOUS_MODULE)

Query Join Condition

I Have two tables named account and assignedgroup. In account table there are two columns named ID and sourceaccount and In assignedgroup I have two columns named ID and assignedgroup.
I want to select ID by joining account and assignedgroup tables. I did something like this:
select a.ID
from account a
left outer join assignedgroup b
on a.sourceaccount = b.assignedgorup
But I get Null as output the reason being that The values in sourceaccount are like this
sourceaccount:
sample
sample
and whereas the values in assignedgroup are like this
assignedgroup:
sample-L1
sample-P-L1
Can anyone help me on how to join these two tables?
I want to get all the ID's whenever there is a sample value in both sourceaccount and assignedgroup.
It is comparing sample with sample-L1 since those are not equal it is returning null but I want the ID even if it has values like that. I mean if somepart of the column values matches then also I want those values to be displayed
SELECT a.id
FROM account a
LEFT JOIN
assignedgroup b
ON b.assignedgorup LIKE a.sourceaccount + '-%'
Clearly your database structure is flawed. If you need the first part of the assigned group to join to the source account, it should be stored that way in a separate column. YOu can do some manipulation to get the right values, but changing the datbase structure is the best fix as any data manipulation you do in a join is very expensive (and likely to introduce bugs).
Since the actual data within those two tables does not actually match, you cannot join those rows in those tables unless you start making some rather broad assumptions about the nature of the data in those tables. For example, this might work:
SELECT a.ID
from Account a
left outer join AssignedGroup b
on a.sourceaccount = left(b.assignedgroup, 6)
or, more generically,
SELECT a.ID
from Account a
left outer join AssignedGroup b
on a.sourceaccount = left(b.assignedgroup, len(a.sourceaccount))
However, this is truly horrible code, logic, and database design, and I would only use this while tyring to troubleshoot and/or fix messed-up data.