SQL - no rows selected after inner join - I don't get it - sql

Ok here are my two tables I'm trying to do a join on, using ORACLE:
FOURNISSEUR
TABLE4
And I'm sorry for copying pictures but I'm having a hard time copying tables from MYSQLPLUS..
I'm trying to do a join on NF but it doesn't seem to work... what am I doing wrong?
SELECT fournisseur.NF,fournisseur.NomF
FROM fournisseur
INNER JOIN table4
ON fournisseur.NF=table4.NF
ORDER BY fournisseur.NF;
And yeah I feel stupid..

Does the NF column in the fournisseur table have spaces after the values?
The column heading for fournisseur.NF looks really wide and appears to be displaying a VARCHAR2(20) (or CHAR(20); but see below) column which could also mean there is extra white-space.
Try trimming the values. e.g.
ON TRIM(fournisseur.NF) = table4.NF
If this indeed works, then I'd look into using CHAR(2), which is hopefully the same type as table4.NF, for fournisseur.NF which would avoid this issue simply by not allowing the extra spaces to begin with.
Since filler spaces on the end of a CHAR(n) field "don't mean anything" then using CHAR(n) types throughout would also remove the observed issue.
Here is a SQL Fiddle, modified from Coat CO's comment, which shows lack-of-join behavior when there are extra spaces in a VARCHAR2(n) column.

Related

Add column with substring of other column in SQL (Snowflake)

I feel like this should be simple but I'm relatively unskilled in SQL and I can't seem to figure it out. I'm used to wrangling data in python (pandas) or Spark (usually pyspark) and this would be a one-liner in either of those. Specifically, I'm using Snowflake SQL, but I think this is probably relevant to a lot of flavors of SQL.
Essentially I just want to trim the first character off of a specific column. More generally, what I'm trying to do is replace a column with a substring of the same column. I would even settle for creating a new column that's a substring of an existing column. I can't figure out how to do any of these things.
On obvious solution would be to create a temporary table with something like
CREATE TEMPORARY TABLE tmp_sub AS
SELECT id_col, substr(id_col, 2, 10) AS id_col_sub FROM table1
and then join it back and write a new table
CREATE TABLE table2 AS
SELECT
b.id_col_sub as id_col,
a.some_col1, a.some_col2, ...
FROM table1 a
JOIN tmp_sub b
ON a.id_col = b.id_col
My tables have roughly a billion rows though and this feels extremely inefficient. Maybe I'm wrong? Maybe this is just the right way to do it? I guess I could replace the CREATE TABLE table2 AS... to INSERT OVERWRITE INTO table1 ... and at least that wouldn't store an extra copy of the whole thing.
Any thoughts and ideas are most welcome. I come at this humbly from the perspective of someone who is baffled by a language that so many people seem to have mastery over.
I'm not sure the exact syntax/functions in Snowflake but generally speaking there's a few different ways of achieving this.
I guess the general approach that would work universally is using the SUBSTRING function that's available in any database.
Assuming you have a table called Table1 with the following data:
+-------+-----------------------------------------+
Code | Desc
+-------+-----------------------------------------+
0001 | 1First Character Will be Removed
0002 | xCharacter to be Removed
+-------+-----------------------------------------+
The SQL code to remove the first character would be:
select SUBSTRING(Desc,2,len(desc)) from Table1
Please note that the "SUBSTRING" function may vary according to different databases. In Oracle for example the function is "SUBSTR". You just need to find the Snowflake correspondent.
Another approach that would work at least in SQLServer and MySQL would be using the "RIGHT" function
select RIGHT(Desc,len(Desc) - 1) from Table1
Based on your question I assume you actually want to update the actual data within the table. In that case you can use the same function above in an update statement.
update Table1 set Desc = SUBSTRING(Desc,2,len(desc))
You didn't try this?
UPDATE tableX
SET columnY = substr(columnY, 2, 10 ) ;
-Paul-
There is no need to specify the length, as is evidenced from the following simple test harness:
SELECT $1
,SUBSTR($1, 2)
,RIGHT($1, -2)
FROM VALUES
('abcde')
,('bcd')
,('cdef')
,('defghi')
,('e')
,('fg')
,('')
;
Both expressions here - SUBSTR(<col>, 2) and RIGHT(<col>, -2) - effectively remove the first character of the <col> column value.
As for the strategy of using UPDATE versus INSERT OVERWRITE, I do not believe that there will be any difference in performance or outcome, so I might opt for the UPDATE since it is simpler. So, in conclusion, I would use:
UPDATE tableX
SET columnY = SUBSTR(columnY, 2)
;

Automatically generated SQL code throws type mismatch

My problem is that I would like to make an append query in Ms-Access 2010. I tried to realize it in query designer, but it throws an error:
Type mismatch in expression
See the generated code below:
INSERT INTO Yield ( ProcessName, Sor, Lot,
ProcessCode, Outgoing, DefectReason, DefectQty, ModifyQty )
SELECT Process.[ProcessName], Sor.[Sor], Qty.[Lot], Qty.[ProcessCode],
Qty.[Outgoing Date], Qty.[Defect Reason], Qty.[Defect Qty], Qty.[Modify_Qty]
FROM (Sor INNER JOIN ProcessCode ON Sor.[SorID] = ProcessCode.[SorID])
INNER JOIN (Process INNER JOIN Qty ON Process.[ProcessID] = Qty.[ProcessID])
ON ProcessCode.[ProcessID] = Process.[ProcessID];
The tables and the attributes are all existing. The ID numbers are indexes, the Quantities are numerical, the 'ProcessName', 'Sor', 'Lot', 'ProcessCode', 'DefectReason' attributes are strings.
What could be the problem?
Thanks in advance.
Looks ok. The best advice is divide it in smaller pieces.
http://importblogkit.com/2015/05/how-do-you-eat-an-elephant/ .
Try this:
Remove the insert part. Just try the select to make sure the join are working properly. If this fail the problem is on the join fields
Then, Put the insert again, but instead of putting table fields from the SELECT use default values. '' for strings and 0 for numeric and put the right alias for column name. That way you make sure your data is bringing the right data type. If this fail then one of the field isnt really a string or a number. Like gustav suggest probably a DATE
If that work then try to put one table field each time until you find the one causing the problem. Maybe one field doesnt support null or is receiving a bigger value than supported.
The problem was that the Yield table did not have the listed attributes. I thought that if some of the listed output attributes are not included in the output table, Access automatically creates the missing new attributes. I was wrong. The output table has to contain the attributes (rows), new attributes cannot be inserted into it this way.

Join BIGINT to VARCHAR, where VARCHAR contains only a small number of non-numeric characters

I'm trying to join two fact tables in a Netezza DB on a common acct_nbr field. In table a, it's BIGINT, and in table b it's coded as VARCHAR. (I have no control over the table design, and I suspect it's set up as VARCHAR because it's populated by web input, and needs to be able to tolerate typos.) I'd like to disregard the alpha characters for the join - I'm willing to rule out all fields in table b that contain non-numeric characters. (The field also contains -,?,!, etc.)
I've tried the following:
A basic join. Throws Bad int8 representation for '9999R99999', I assume based on the first non-convertible VARCHAR entry it comes across.
Using cast/convert on both fields (to BIGINT for b.acct_nbr, to VARCHAR for a.acct_nbr) which I may have implemented incorrectly. Various errors, no results.
Using "select ... from table_a a join table_b b on (a.acct_nbr=b.acct_nbr and b.acct_nbr not like '%[^0-9]%')". I don't seem to be able to make this work, and I haven't found a good explanation for how the '%[]%' syntax works. I know what % does, but I've a poor understanding of how to use the carat and the brackets.
I'm sure this is a simple problem, but I'm banging my head against the wall. Any help is much appreciated!
You can complete the join a few different ways.
select ...
from table_a a join
table_b b on (a.acct_nbr=b.acct_nbr
and translate(b.acct_nbr,'1234567890','') in ('','.','-','-.')
Or if you have the sql functions toolkit installed you could do this.
select ...
from table_a a join
table_b b on
(a.acct_nbr=sql_functions..regexp_extract(b.acct_nbr,'^[0-9]{1,18}')

How to delete a common word from large number of datas in a Postgres table

I have a table in Postgres. In that table more than 1000 names are there. Most of the names are start with SHRI or SMT. I want to delete this SHRT and SMT from the names and to save original name only. How can I do that with out any database function?
I'll step you through the logic:
Select left(name,3) from table
This select statement will bring back the first 3 chars of a column (the 'left' three). If we are looking for SMT in the first three chars, we can move it to the where statement
select * from table where left(name,3) = 'SMT'
Now from here you have a few choices that can be used. I'm going to keep to the left/right style, though replace could likely be used. We want the chars to the right of the SMT, but we don't know how long each string is to pick out those chars. So we use length() to determine that.
select right(name,length(name)-3) from table where left(name,3) = 'SMT'
I hope my syntax is right there, I'm lacking a postgres environment to test it. The logic is 'all the chars on the right of the string except the last 3 (the minus 3 excludes the 3 chars on the left. change this to 4 if you want all but the last 4 on the left)
You can then change this to an update statement (set name = right(name,length(name)-3) ) to update the table, or you can just use the select statement when you need the name without the SMT, but leave the SMT in the actual data.

Joining varchar and nvarchar

I'm comparing account numbers in two different databases to make sure the account exists in both. The account field in one database is nvarchar and the other it's varchar. I do a cast to cast them both to varchar(12) and join them to see where there isn't a match. If there is an account number with less than 12 characters then it thinks it's not a match. I'm assuming the extra characters in each field are causing the issue?
table1 - accountnumber(nvarchar(255))
table2 - accountnumber(varchar(20))
select * from
table1
left outer join table2 on table2.accountnumber = table1.accountnumber
In this one example, both tables have an account with the number 12345678, but the join isn't working. I'm not sure if it's data type mismatch or white space or something else.
--Added--
I should add that the data in table2 actually originates from an Oracle database where it's stored as a varchar2(12 byte). I import it into a SQL Server database where it's stored as a varchar(20). I'm not sure if this makes a difference.
Not sure where you are having a problem. This query should return matching account numbers (no need to CAST):
SELECT *
FROM YourTable
JOIN YourOtherTable ON YourTable.AccountNumber = YourOtherTable.AccountNumber
If your data has spaces, you can TRIM your data depending on your RDBMS -- LTRIM and RTRIM for SQL Server.
SELECT *
FROM YourTable
JOIN YourOtherTable ON RTRIM(LTRIM(YourTable.AccountNumber)) = RTRIM(LTRIM(YourOtherTable.AccountNumber))
Here is the SQL Fiddle.
Good luck.
Your query works fine. This is perhaps a character encoding issue. Try using collate. See this previous SO answer which might help.
I ran into absolutely same case, I had even two sibling queries (one created as a copy of another), which both had this problem. Collation and types were no issue here.
Finally after a LOT of testing, one of the queries started to work without aparent changes, just re-written. When I retyped the IN part of the second query, it started to work too.
So there was a problem with a hidden character accidentally typed somewhere in the query.