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

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.

Related

Compare 2 Tables and write RowID from Table A to Table B

I have Table A with RowID, Date, Vendor and Cost, Confirmed
I have table B with RowID, Date, Vendor and Cost, Confirmed
Table A list our purchases.
Table B list the statement data from the credit card.
I would like to compare Date, Vendor and Cost in Table A with the same columns in Table B. If there is a match with those three columns, then I would like to take the RowID value from Table A and write it to the matching row in Table B under the Confirmation column.
I am very new to SQL and I am not even sure this is a reasonable expectation.
What do you think?
Is this enough detail to provide your opinion?
Thank you for any help you can give.
Currently I am using an Outer Right Join to get all the rows that do NOT have a match. What I really need is the opposite.
It might help to know what database engine you are using...
My answers are going to relate to MS SQL Server, but much SQL Syntax is the same...
To answer your first question, I would write something like:
Update TableB Set Confirmation = TableA.RowID From TableA
Where TableA.Vendor = TableB.Vendor
And TableA.Cost = TableB.Cost
And TableA.Date = TableB.Date
I would use aliases, but I left them out to hopefully make it easier to understand.
To answer your second question, you can specify an INNER JOIN which is the opposite of an OUTER JOIN and as you mentioned, what you are looking for, as it will return ALL rows that Match and exclude the rest.
You can do this with this query
UPDATE
B
SET
Confirmation = A.RowID
FROM
TableA A
INNER JOIN TableB B
ON B.Vendor = A.Vendor
AND B.Cost = A.Cost
AND B.Date = A.Date
Basically we do an inner join to keep the intersection (the records that match) of the two tables. and update the records that coincided from table B with the id of table A

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 :-)

Having issues using a Right Join in MS Access 2010 with two tables that have the same fields

I have two tables, Table A and Table B. Each table have 4 fields, the name of the fields are the same for both. Both tables are extracted from other tables, and each record acts as a primary key.
I want to write a query in MS Access 2010 that gets the data unique to Table B and not shared with Table A. I am using the following image as a reference, and it looks like I need to do a Right Join.
Hello. There is something not right with my SQL, I've tested it and I am getting the incorrect result. Below is the closest I've gotten:
SELECT DISTINCT TableB.*
FROM TableB RIGHT JOIN TableA ON (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
WHERE (((TableA.Field1) Is Null));
I think it would be clearer for you to use not exists:
select tableb.*
from tableb
where not exists (select 1
from tablea
where (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
);
Your use of RIGHT JOIN is incorrect. As phrased, you want a LEFT JOIN. That is, you want to keep all rows in the first table (the "left" table in the JOIN) regardless of whether or not a match exists in the second table. However, the NOT EXISTS does the same thing and the logic is a bit clearer.
You want to have right join if tablea is in your select statement, but as you have
SELECT DISTINCT TableB.*
you may want to have a left join instead. My suggestion would be changing your code from right to left join.
TableB acts like table A from venn diagrams above.

Getting way more results than expected in SQL left join query

My code is such:
SELECT COUNT(*)
FROM earned_dollars a
LEFT JOIN product_reference b ON a.product_code = b.product_code
WHERE a.activity_year = '2015'
I'm trying to match two tables based on their product codes. I would expect the same number of results back from this as total records in table a (with a year of 2015). But for some reason I'm getting close to 3 million.
Table a has about 40,000,000 records and table b has 2000. When I run this statement without the join I get 2,500,000 results, so I would expect this even with the left join, but somehow I'm getting 300,000,000. Any ideas? I even refered to the diagram in this post.
it means either your left join is using only part of foreign key, which causes row multiplication, or there are simply duplicate rows in the joined table.
use COUNT(DISTINCT a.product_code)
What is the question are are trying to answer with the tsql?
instead of select count(*) try select a.product_code, b.product_code. That will show you which records match and which don't.
Should also add a where b.product_code is not null. That should exclude the records that don't match.
b is the parent table and a is the child table? try a right join instead.
Or use the table's unique identifier, i.e.
SELECT COUNT(a.earned_dollars_id)
Not sure what your datamodel looks like and how it is structured, but i'm guessing you only care about earned_dollars?
SELECT COUNT(*)
FROM earned_dollars a
WHERE a.activity_year = '2015'
and exists (select 1 from product_reference b ON a.product_code = b.product_code)

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;