Tag Archive: SQL Examples


Improper column reference in the search condition of a joined table


Usually you want a quick easy response to the problem that you are searching for the solution to on the web, right?  Well here are two common reasons (with example code) why you may be receiving this error:

1.) On your join statement, your ON or AND statements are asking to join columns on a different table other than the two tables that you are originally intending to join.

Example:

 SELECT A.CUST_ID, B.CUST_NAME, C.CUST_ADDRESS
 FROM TD.CUSTOMER_REF A
 LEFT JOIN TD2.CUST_INFO B
      ON B.CUST_ID = A.CUST_ID
      AND B.CUST_REF = C.CUST_REF /*this should be A.CUST_REF as opposed to C.CUST_REF*/
 LEFT JOIN TD3.CUST_SHIPPING C
      ON  C.CUST_ID = A.CUST_ID
      AND C.CUST_REF = A.CUST_REF

The bolded line is written incorrectly because although TD3.CUST_SHIPPING does have a CUST_REF column, it should not be a join criteria for the second left join.

2.) Another scenario where this can occur is when you join a table using a where clause and a join.  I can’t give you the specifics as to why it works the way it does, but when your second table reference preceeds the left join you are likely to get this error.  The rule of thumb that I have followed and had success with is to have the join follow the table you plan to join on.  This is likely to prevent other errors too. 

See the syntax examples below for correct and incorrect way of joining tables using joins and where clauses.

Example of incorrect way to use Joins and Where clauses

SELECT A.CUST_ID, B.CUST_NAME, C.CUST_ADDRESS
 FROM TD.CUSTOMER_REF A,
 TD3.CUST_SHIPPTING C

 LEFT JOIN TD2.CUST_INFO B
 ON B.CUST_ID = A.CUST_ID
 WHERE C.CUST_ID = A.CUST_ID
 AND C.CUST_REF = A.CUST_REF

 

Example of correct way to use Joins and Where clauses

SELECT A.CUST_ID, B.CUST_NAME, C.CUST_ADDRESS
 FROM TD.CUSTOMER_REF A
 LEFT JOIN TD2.CUST_INFO B
 ON B.CUST_ID = A.CUST_ID
 TD3.CUST_SHIPPTING C
 WHERE C.CUST_ID = A.CUST_ID
 AND C.CUST_REF = A.CUST_REF

As you can see, the placement of the line in bold is the difference between these queries working (or not).  As a side note, the query techniques mentioned above have been tested on both the Teradata and DB2 zOS environments and have proven successful.  Other databases such as MySQL may be more lax and accept your SQL as is.

Using a SAS dataset and SQL table in PROC SQL


If you are reading this it is because you have written a PROC SQL statement where you reference both a dataset that you created in an earlier step and a table that resides on an RDBMS (such as SQL Server, MySQL, Teradata, etc . .  .).

Well before you go any further I have to tell you that so far it is not possible to combine the results of a SAS data set and an DBMS table within one PROC-SQL-CREATE-TABLE-AS statement.

For example with the following code I would get an ODBC error saying that "object LIBRARY.SASDATASET1 is not an object in RDBMS …"

PROC SQL;

 

CONNECT TO ODBC AS DSNNAME(DATASRC=DSN USER=USERNAME PASSWORD=PASSWORD);

 

CREATE TABLE LIBRARY.SASDATASET1 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, NAME, SSN FROM SQLDB.TABLE_EMP_ID);

 

 

CREATE TABLE LIBRARY.SASDATASET2 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, JOB_TITLE, SALARY

 FROM SQLDB.TABLE_EMP_SALARY SAL,

      LIBRARY.SASDATASET1 SDS

 WHERE SAL.ID = SDS.ID)

 

 DISCONNECT FROM DSNNAME;

 

 QUIT;

 

What you will have to do instead is make a copy of the SASDATASET1 to your SQL database (Teradata, MySQL, SQLServer, etc…) and then rewrite the second create table statement with your join pointing not to the SAS dataset but rather the table that was created from your first dataset.

 

 

PROC SQL;

 

CONNECT TO ODBC AS DSNNAME(DATASRC=DSN USER=USERNAME PASSWORD=PASSWORD);

 

CREATE TABLE LIBRARY.SASDATASET1 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, NAME, SSN FROM SQLDB.TABLE_EMP_ID);

 

 

CREATE TABLE LIBRARY.SASDATASET2 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, JOB_TITLE, SALARY

 FROM SQLDB.TABLE_EMP_SALARY SAL,

      LIBRARY.SASDATASET1 SDS

 WHERE SAL.ID = SDS.ID)

 

 DISCONNECT FROM DSNNAME;

 

 QUIT;

 

 

 

 

 

 PROC SQL;

 

CONNECT TO ODBC AS DSNNAME(DATASRC=DSN USER=USERNAME PASSWORD=PASSWORD);

 

CREATE TABLE LIBRARY.SASDATASET1 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, NAME, SSN FROM SQLDB.TABLE_EMP_ID);

 

QUIT;

 

PROC COPY;

IN=LIBRARY OUT=ODBCLIB MTYPE=(DATA);

SELECT SASDATASET1;

QUIT;

 

PROC SQL;

 

CREATE TABLE LIBRARY.SASDATASET2 AS

SELECT * FROM CONNECTION TO DSNNAME

(SELECT ID, JOB_TITLE, SALARY

 FROM SQLDB.TABLE_EMP_SALARY SAL,

      SQLDB.SASDATASET1 SDS

 WHERE SAL.ID = SDS.ID)

 

 DISCONNECT FROM DSNNAME;

 

 QUIT;

 

Questions?  Please post a comment.

Derive new fields from one column using SQL Join


The majority of tables that record transactional data contain many years of transactional data.  So if you wanted to compare sales in 2007 to sales and 2008, it may be a little tricky considering that the sales figure for any year are stored in the same column.

For example:

<strong>CLIENT            STMT_DATE       PURCHASES
</strong>BUTERBROD CO      2007-10-31      3490561
BUTERBROD CO      2007-11-30      3313900
BUTERBROD CO      2008-01-31      3292238
BUTERBROD CO      2008-02-29      3325060
BUTERBROD CO      2008-03-31      3680350

You will notice that this section of data in our cust_sales table 2007 and 2008 purchase values are in the same table.  So how can we query or create a data set that will compare January 2007 against January 2008 sales?  The answer is through SQL joins.  Essentially we will create two aggregate function queries.  One that calls for the sum sales in 2008 and we will join it with a second query that will call for the sum sales for sales that occured in the year 2007.  (Note – To test example, download SQL file and attempt on your database)

<span style="font-size: larger"><span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">SELECT</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> S08.CUST_ID, S08.STMT_DT, SUM(S08.PURCHASES) </font><span style="color: #0070c0">AS</span><font color="#000000"> PURCH_08, S07.PURCH_07</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font><span style="font-size: larger">
<span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">FROM</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> CUST_SALES S08
</font></span><span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">LEFT</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> </font><span style="color: #0070c0">JOIN</span><font color="#000000"> (SELECT CUST_ID, STMT_DT, SUM(PURCHASES) </font><span style="color: #0070c0">AS</span><font color="#000000"> PURCH_07</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font><span style="font-size: larger">
<span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><span style="mso-spacerun: yes"><font color="#000000">                   </font></span><span style="color: #0070c0">FROM</span><font color="#000000"> CUST_SALES</font></span></span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font size="3"><font color="#000000"><o:p></o:p></font></font></span><span style="font-size: larger">
<span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><span style="mso-spacerun: yes"><font color="#000000">                   </font></span><span style="color: #0070c0">WHERE</span><font color="#000000"> YEAR(STMT_DT) = 2007</font></span></span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font size="3"><font color="#000000"><o:p></o:p></font></font></span><span style="font-size: larger">
<span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><span style="mso-spacerun: yes"><font color="#000000">                   </font></span><span style="color: #0070c0">GROUP BY</span><font color="#000000"> CUST_ID, STMT_DT) S07</font></span></span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font size="3"><font color="#000000"><o:p></o:p></font></font></span><span style="font-size: larger">
<span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">ON</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> S07.CUST_ID = S08.CUST_ID</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font><span style="font-size: larger">
<span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">AND</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> MONTH(S07.STMT_DT) = MONTH(S08.STMT_DT)</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font><span style="font-size: larger">
<span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">WHERE</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> YEAR(S08.STMT_DT) = 2008</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font><span style="font-size: larger">
<span style="color: #0070c0; font-family: 'Courier New'; mso-bidi-font-size: 12.0pt">GROUP BY</span><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"> S08.CUST_ID, S08.STMT_DT, S07.PURCH_07</font></span></span><font size="3"><span style="font-family: 'Courier New'; mso-bidi-font-size: 12.0pt"><font color="#000000"><o:p></o:p></font></span></font>&nbsp;

The above query will provide us with the following results:

CLIENT            STMT_DATE       PURCH_08     PURCH_07
BUTERBROD CO      2008-03-31      3680350      3184136
BUTERBROD CO      2008-04-30      3714286      3027849
BUTERBROD CO      2008-05-31      4104875      3369345
BUTERBROD CO      2008-06-30      4217168      3462368
BUTERBROD CO      2008-07-31      4288708      3486339
BUTERBROD CO      2008-08-31      4308599      3590772
BUTERBROD CO      2008-09-30      4034318      3410853
BUTERBROD CO      2008-10-31      4090400      3490561
BUTERBROD CO      2008-11-30      3965514      3313900

If you are needing the calculate the difference between 2008 and 2007, you can create a new column by subtracting 2008 purchases from 2007.  The SQL for that is:

<span style="color: #0000ff">SELECT</span> S08.CUST_ID, S08.STMT_DT, SUM(S08.PURCHASES) <span style="color: #0000ff">AS</span> PURCH_08,  S07.PURCH_07,
             SUM(S08.PURCHASES) - S07.PURCH_07 <span style="color: #0000ff">AS</span> DIFF
<span style="color: #0000ff">FROM</span> CUST_SALES S08
<span style="color: #0000ff">LEFT</span> JOIN (SELECT CUST_ID, STMT_DT, SUM(PURCHASES) AS PURCH_07
                   <span style="color: #0000ff">FROM</span> CUST_SALES
                   <span style="color: #0000ff">WHERE</span> YEAR(STMT_DT) = 2007
                   <span style="color: #0000ff">GROUP BY</span> CUST_ID, STMT_DT) S07
<span style="color: #0000ff">ON </span>S07.CUST_ID = S08.CUST_ID
<span style="color: #0000ff">AND</span> MONTH(S07.STMT_DT) = MONTH(S08.STMT_DT)
<span style="color: #0000ff">WHERE </span>YEAR(S08.STMT_DT) = 2008
<span style="color: #0000ff">GROUP BY</span> S08.CUST_ID, S08.STMT_DT, S07.PURCH_07

Look for my REGR_SLOPE() SQL post.  Using it may be the next step you want to take in your analysis.