Convert columnB value if columnA = X in SQL - 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 :-)

Related

Use switch and "in" in MS-Access Select Query

let's say I have two tables, where the first one contains my data:
Automatic
Manual
X1
X1
Y
Y27
and a lookup table
Lookup
X1
Y27
...
I want to select the value from the first table, IF it is contained in the lookup table.
So for the second row, it should take the value Y27, because Y ist not in the lookup table.
I tried it with this query:
Select
Switch(
Automatic in (SELECT Lookup FROM LookupTable), Automatic,
True, Manual,
) AS ValidEntry
FROM Datatable;
My query as text: Check if the value from "Automatic" is inside the lookup table, if yes -> take the value, if not, take the value from the other column "manual" and return an entry named "ValidEntry".
Use a INNER JOIN, it should be much faster.
select somedata from table1 t
inner join lookupTbl l on l.lookupfield = t.automatic
With IN clause:
select somedata from table1 t
WHERE t.automatic IN (select lookupfield FROM lookupTbl)
This is what you need to do:
SELECT NZ( LookupTableAutomatic.Lookup, LookupTableManual.Lookup) AS Lookup
FROM (LookupTable AS LookupTableManual INNER JOIN DataTable
ON LookupTableManual.Lookup = DataTable.Manual)
LEFT OUTER JOIN LookupTable AS LookupTableAutomatic ON LookupTableAutomatic.Lookup = DataTable.Automatic;
By way of explanation the NZ Function returns the first parameter if it is not null, otherwise it takes the second. The lookup table is joined twice: the Manual Lookup is an INNER JOIN, as I am assuming that there will always be a fallback value, whereas the Automatic lookup is joined as an OUTER JOIN, meaning that it returns NULL when the value is not matched.

SQLite: distinguish between table and column alias

Can SQLite distinguish between a column from some aliased table, e.g. table1.column and a column that is aliased with the same name, i.e. column, in the SELECT statement?
This is relevant because I need to refer to the column that I construct in the SELECT statement later on in a HAVING clause, but must not confuse it with the column in aliased table. To my knowledge, I cannot alias the table to be constructed in my SELECT statement (without reverting to some nasty work-around like SELECT * FROM (SELECT ...) AS alias) to ensure both are distinguishable.
Here's a stripped down version of the code I am concerned with:
SELECT
a.entity,
b.DATE,
TOTAL(a.dollar_amount*b.ret_usd)/TOTAL(a.dollar_amount) AS ret_usd
FROM holdings a
LEFT JOIN returns b
ON a.stock = b.stock AND
a.DATE = b.DATE
GROUP BY
a.entity,
b.DATE
HAVING
ret_usd NOT NULL
Essentially, I want to get rid of groups for which I cannot find any returns and thus would show up with NULL values. I am not using an INNER JOIN because in my production code I merge multiple types of returns - for some of which I may have no data. I only want to drop those groups for which I have no returns for any of the return types.
To my understanding, the SQLite documentation does not address this issue.
LEFT JOIN all the return tables, then add a WHERE something like
COALESCE(b.ret_used, c.ret_used, d.ret_used....) is not NULL
You might need a similar strategy to determine which ret_used in the TOTAL. FYI, TOTAL never returns NULL.

PostgreSQL Query Not Returning Data

I have 2 tables (tabl1 and tbl2) and I want a query that joins tbl2 to tbl1 by matching its col1id and col2id so that the result set contains the tbl1 data with the name column in tbl2.
The following query returns no data:
SELECT Date
,cast(tbl1.col1_id as varchar) AS "col1name"
,tbl2.name::varchar AS "tabl2name"
,tbl1.currency::money as "Avg currency"
,CASE WHEN rich IS NULL then 'Unknown'
ELSE 'True' END AS "bank"
,CAST(Ranking AS FLOAT) / 18 + 1 AS "Rich Ranking"
,tbl1.Reviews as "Reviews"
FROM tbl1
JOIN tbl2
ON tbl1.col1id = tbl2.col2id
tbl1.col1id contains numbers like 3,999,999
When I do a full right join, I am able to get the all the data from the 2 separate tables
I created a new table with certain names I wanted next to it.
I created a new table with values with the exact match of the 3,999,999 and I am getting no matches in the end so I thought types were at fault and I've been messing around with the data a bit and I'm stuck.
I am guessing the values are not the same type, so I did some extra work inputting it either as integer or varchar elsewhere and on the same query.
But the results returned as nothing but did not generate an error so I believe it's a type error on my end.
If you just wanna to do what you describe in your post, better avoid unnecessary complexity. Does the following return anything?
SELECT tbl1.*, tbl2.name
FROM tbl1
JOIN tbl2
ON tbl1.col1id = tbl2.col2id;
If nothing comes back I would first suggest to check if there are any tbl2.col2id that match tbl1.col1id at all.
You could do that easily by using a LEFT JOIN (atm by using JOIN you are using an INNER JOIN really). Your rowset would then contain all rows from tbl1 and have null values in tbl2.name if no join was possible.
Apart from that i would make sure that the datatypes of tbl1.col1id and tbl2.col2id are the same.

SAS SQL JOIN increase rows instead of match rows

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;

(My)SQL how to truncate/split a value to be used elsewhere

I'm not 100% sure what key words I would be using for this to search, so if there are links please post.
I'm not very experienced with SQL, so am not sure what 'tools' are in the toolbox for this..
but basically I want to query one table (Table A)... get a value from the column in each row
(example value(s): 2015013 or 2015164 or even 2015009)
truncate/split that value removing the 2015 pre-text... and get the value at the end.
1.) I'm not sure what tools I should be looking into for this?
2.) I'm not sure how to handle the (possible) leading zero or 2?
here is my (feeble) attempt..minus the SQL parsing..
(hope I'm on the right path?)
SELECT q1.number
FROM TableA q1
LEFT JOIN TableB s1
ON s1.id=q1.number
WHERE survey = '2015New';
so to recap.. I want to query Table A (q1).. parse that value by trimming off the 2015 in front.. as well as any padding/leading zeros.. then use that to query/grab values in TableB (s1) by the newly parsed 'id'.
Hope that makes sense.
thanks.
update:
I have also tried these without much luck.. the second executes but only seems to return one column ..then an error at the bottom:
SELECT q1.number, s1.id, s1.keyword_1, s1.keyword_2
FROM TableA q1
LEFT JOIN TableB s1 ON s1.id=CAST(TRIM(LEADING '0' FROM SUBSTR(q1.survey, 5)) AS UNSIGNED)
WHERE survey = '2015New';
SELECT q1.number, s1.id, s1.keyword_1, s1.keyword_2
FROM TableA q1
LEFT JOIN TableB s1 ON s1.id=TRIM(LEADING '0' FROM CAST(SUBSTR(q1.survey, 5) AS UNSIGNED));
WHERE survey = '2015New';
Assuming the survey field is the one you want to trim
Assuming you want to skip always the 4 first chars
SELECT fields
FROM TableA q1
LEFT JOIN TableB s1 ON s1.id=CAST(SUBSTR(q1.survey, 5) AS UNSIGNED)
WHERE survey = '2015New';
But this is horrible, you should think of redesigning your model... The number should be stored as a column all by itself, indexed, and used to join with other tables.