proc sql code in SAS not filtering properly - sql

I hope this is not a very very obvious, but if it is please don't kill me, I'm really new at this and struggle to find much info.
This code should do the following:
-grab columns from 2 different tables
-only select rows that are not on a third table on a particular date
proc sql;
create table DiallerExtra as
SELECT a.AGREEMENT_NUMBER,
b.CURRENT_FIRST_NAME,
b.TELEPHONE_NUMBER
FROM TABLE1 a, TABLE2 b
WHERE a.AGREEMENT_NUMBER
NOT IN (SELECT AgreementNumber
FROM TABLE3 (WHERE =(DeleteDate >= today()-1)))
;
quit;
I first tried this (below) and it worked fine to filter the results (I ended up with 15 rows only).
proc sql;
create table DiallerExtra as
SELECT a.AGREEMENT_NUMBER
FROM TABLE1 a
WHERE a.AGREEMENT_NUMBER
NOT IN (SELECT AgreementNumber
FROM TABLE3 (WHERE =(DeleteDate >= today()-1)))
;
quit;
But when I tried the first code, it doesn't seem to be filtering correctly cause it spits out all the agreements on TABLE2, which is a lot.

The "filtering" of your NOT IN logic is not the problem.
Add something to tell SQL how to combine TABLE1 and TABLE2.
If you want to combine two tables with SQL you need to tell it how to match the observations. Otherwise every observation in TABLE1 is matched to every observation in TABLE2. In your first example even if there is only one observation in TABLE1 with a value of A.AGREEMENT_NUMBER that is in the TABLE3 observations that match your WHERE= dataset option then it will be matched with every observation in TABLE2. So if TABLE2 had 100 customers the result set will have 100 observations.
So add another condition to your WHERE statement. For example if both TABLE1 and TABLE2 have AGREEMENT_NUMBER then perhaps you want to match on that.
create table DiallerExtra as
SELECT a.AGREEMENT_NUMBER
, b.CURRENT_FIRST_NAME
, b.TELEPHONE_NUMBER
FROM TABLE1 a
, TABLE2 b
WHERE a.AGREEMENT_NUMBER = b.AGREEMENT_NUMBER
and a.AGREEMENT_NUMBER NOT IN
(SELECT AgreementNumber FROM TABLE3 (WHERE =(DeleteDate >= today()-1)))
;

Related

Copy all the values from table1 to table2 only if condition met

Let's say var_Environment = QA1,QA2.
I have two tables table 1 and table 2. Table 1 has some column name var_Environment =QA1; where as table 2 does have the same column name but no values
Now my task is, I need to copy all the values from table1 to table2 only if condition meets var_Environment =QA2 How will I perform this operation ? Can I use Union All with some condition? Can someone help?
You can use INSERT INTO SELECT like below.
The WHERE clause may need adjustment, so run the the SELECT query by itself to check if the correct rows are selected.
INSERT INTO table2
SELECT var_Environment
FROM Table1
WHERE var_Environment LIKE '%QA2%'

SQL: Add multiple rows from one table to another when no data for that date in new table

I'm trying to update medical data from one table to another after switching from one system to another. We have two tables, for simplicity I'll make this a simple example. There are many columns in these tables in reality (not just 5).
Table1:
name, date, var1, var2, var3
Table2:
name, date, var1a, var2a, var3a
I want to transfer data from Table 1 to Table 2 for any rows where there isn't previous data for that date, where var1 = var1a, etc (same columns with different names).
I was trying to do something with a loop, but realized that may not be necessary.
I had gotten this far but keep wasn't sure if this was ok:
UPDATE Table2 VALUES (date, var1a, var2a, var3a)
SELECT date, var1, var2, var3 FROM Table1
Is that correct syntax so far? Or do I need to map the variables to translate var1 into var1a, etc?
How do I add a check to make sure I don't overwrite any data already in Table1? I don't want to add data if there is already data for that date/name combination.
Thanks!
You can INSERT into TABLE2 all values from TABLE1 that do not already exist in Table2:
INSERT INTO Table2 (date, var1a, var2a, var3a)
SELECT date, var1, var2, var3
FROM Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM Table2 t2 WHERE t2.date = t1.date)
Already existing values are specified by comparing the date column. You can add any other predicates in the SELECT subquery of the NOT EXISTS expression to suit your needs.
You could use an update with a join. And you dont need to update the date column since that's what you are using to find the matches in the 2 tables.
Either you generate a dynamic query based on the empty/null valued columns, or you could do something like the below, which puts the same value in the column if it exists in table2 or else puts the corresponding value from table1.
The below approach requires less logic and easier to implement but will produce IO equivalent to updating the entire table.
update tbl2
set val1a=isnull(val1a,val1)
, val2a=isnull(val2a,val2)
, val3a=isnull(val3a.val3)
from table1 tbl1
inner join table2 tbl2
on tbl1.name=tbl2.name
and tbl1.date=tbl2.date
Considerations:
The approach requires less logic and easier to implement but will produce IOs equivalent to updating the entire table2. If you have a smallish table i would go with this approach.
If its a big table then you should look into building specific query sets to reduce IO
This code is tested in Access but something very similar should work in SQL Server 2012:
UPDATE Table2 RIGHT JOIN Table1 ON Table2.date = Table1.date
SET Table2.name = Table1.name, Table2.date = Table1.date, Table2.var1 = Table1.var1a, Table2.var2 = Table1.var2a, Table2.var3 = Table1.var3a
WHERE (Table2.date Is Null);
Explanation: this uses a right join so that within the query all the data from Table1 is present and where there is a matched date for Table2 that data is present too. We then ignore all cases where there is any data for Table2 and update the query in all other cases - the update in fact inserts new data into Table2.

Select values from one table depending on referenced value in another table

I have two tables in my SQLite Database (dummy names):
Table 1: FileID F_Property1 F_Property2 ...
Table 2: PointID ForeignKey(fileid) P_Property1 P_Property2 ...
The entries in Table2 all have a foreign key column that references an entry in Table1.
I now would like to select entries from Table2 where for example F_Property1 of the referenced file in Table1 has a specific value.
I tried something naive:
select * from Table2 where fileid=(select FileID from Table1 where F_Property1 > 1)
Now this actually works..kind of. It selects a correct file id from Table1 and returns entries from Table2 with this ID. But it only uses the first returned ID. What I need it to do is basically connect the returned IDs from the inner select by OR so it returns data for all the IDs.
How can I do this? I think it is some kind of cross-table-query like what is asked here What is the proper syntax for a cross-table SQL query? but these answers contain no explaination of what they are actually doing so I'm struggeling with any implementation.
They are using JOIN statements, but wouldn't this mix entries from Table1 and Table2 together while only checking matching IDs in both tables? At least that is how I understand this http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
As you may have noticed from the style, I'm very new to using databases in general, so please forgive me if not everything is clear about what I want. Please leave a comment and I will try to improve the question if neccessary.
The = operator compares a single value against another, so it is assumed that the subquery returns only a single row.
To check whether a (column) value is in a set of values, use IN:
SELECT *
FROM Table2
WHERE fileid IN (SELECT FileID
FROM Table1
WHERE F_Property1 > 1)
The way joins work is not by "mixing" the data, but sort of combining them based on the key.
In your case (I am assuming the key field in Table 1 is unique), if you join those two tables on the primary key field, you will end up with all the entries in table2 plus all corresponding fields from table1. If you were doing this:
select * from table1, table2 where table1.fieldID=table2.foreignkey;
then, providing your key fields are set up right, you will end up with the following:
PointID ForeignKey(fileid) P_Property1 P_Property2 FileID F_Property1 F_Property2
The field values from table1 would be from matching rows.
Now, if you do this:
select table1.* from table 1, table2 where
table1.fieldID=table2.foreignkey and F_Property1>1;
Would essentially get the same set of records, but will only show the columns from the second table, and only those that satisfy the where condition for the first one.
Hope this helps :)
If I understood your question correctly this will get the job done.
Select t2.*
from table1 t1
inner join table2 t2 on t2.id = t1.id
where t1.Prop = 'SomeValue'

how to compare two rows in one mdb table?

I have one mdb table with the following structure:
Field1 Field2 Field3 Field4
A ...
B ...
I try to use a query to list all the different fields of row A and B in a result-set:
SELECT * From Table1
WHERE Field1 = 'A'
UNION
SELECT * From Table1
WHERE Field1 = 'B';
However this query has two problems:
it list all the fields including the
identical cells, with a large table
it gives out an error message: too
many fields defined.
How could i get around these issues?
Is it not easiest to just select all fields needed from the table, based on the Field1 value and group on the values needed?
So something like this:
SELECT field1, field2,...field195
FROM Table1
WHERE field1 = 'A' or field1 = 'B'
GROUP BY field1, field2, ....field195
This will give you all rows where field1 is A or B and there is a difference in one of the selected fields.
Oh and for the group by statement as well as the SELECT part, indeed use the previously mentioned edit mode for the query. There you can add all fields (by selecting them in the table and dragging them down) that are needed in the result, then click the 'totals' button in the ribbon to add the group by- statements for all. Then you only have to add the Where-clause and you are done.
Now that the question is more clear (you want the query to select fields instead of records based on the particular requirements), I'll have to change my answer to:
This is not possible.
(untill proven otherwise) ;)
As far as I know, a query is used to select records using for example the where clause, never used to determine which fields should be shown depending on a certain criterium.
One thing that MIGHT help in this case is to look at the database design. Are those tables correctly made?
Suppose you have 190 of those fields that are merely details of the main data. You could separate this in another table, so you have a main table and details table.
The details table could look something like:
ID ID_Main Det_desc Det_value
This way you can filter all Detail values that are equal between the two main values A and B using something like:
Select a.det_desc, a.det_value, b.det_value
(Select Det_desc, det_value
from tblDetails
where id_main = a) as A inner join
(Select Det_desc, det_value
from tblDetails
where id_main = a) as B
on A.det_desc = B.det_desc and A.det_value <> B.det_value
This you can join with your main table again if needed.
You can full join the table on itself, matching identical rows. Then you can filter on mismatches if one of the two join parts is null. For example:
select *
from (
select *
from Table1
where Field1 = 'A'
) A
full join
(
select *
from Table1
where Field1 = 'B'
) B
on A.Field2 = B.Field2
and A.Field3 = B.Field3
where A.Field1 is null
or B.Field1 is null
If you have 200 fields, ask Access to generate the column list by creating a query in design view. Switch to SQL view and copy/paste. An editor with column mode (like UltraEdit) will help create the query.

Matching records with wild cards from two different tables

I have two tables with the following data (amongst other data).
Table 1
Value 1
'003232339639
'00264644106272
0026461226291#
I need to match the second column in the table below using column 1 as an identifier
Table 2
Value 1 Value 2
00264 1
0026485 2
0026481 3
00322889 4
00323283 5
00323288 6
So the results I need will be as follows:
Result
Table 1, Value 1 Table 2, Value 2
'003232339639......4
'00264644106272....1
0026461226291#.....1
Any help will be appreciated - very stuck here and doing it manually at the moment in excel.
I hope this format makes sense - first time I am using this forum.
Melany, the question is kind of confusing (not written correctly) perhaps that's why no one is responding. I'll make an attempt to explain how similar selects is done
SELECTING DATA FROM TABLE1 WHERE A MATCHING COLUMN (COL1) EXISTS IN BOTH TABLE
SELECT * FROM TABLE1
INNER JOIN TABLE2
ON TABLE1.COL1 = TABLE2.COL1
AND TABLE1.COL1 = 'XYZ'
USING A SUBSELECT FOR THE SAME
SELECT * FROM TABLE1
WHERE COL1 IN(SELECT COL1 FROM TABLE2
WHERE COL1 = 'XYZ')
In SQL, the wildcard for one or more characters is %, and is to be used with the keyword LIKE.
So I suggest the following (if your purpose is really to match rows in Table1 for which Value1 begins like a value in Table2.Value1):
SELECT Table1.Value1, Table2.Value2 WHERE Table1.Value1 LIKE CONCAT(Table2.Value1, '%');
Edit: replace CONCAT(x, y) with x || y for some DBMSs (SQLite for instance).