How to inner-join in Excel (eg. using VLOOKUP) - sql

Is there a way to inner join two different Excel spreadsheets using VLOOKUP?
In SQL, I would do it this way:
SELECT id, name
FROM Sheet1
INNER JOIN Sheet2
ON Sheet1.id = Sheet2.id;
Sheet1:
+----+------+
| ID | Name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+----+------+
Sheet2:
+----+-----+
| ID | Age |
+----+-----+
| 1 | 20 |
| 2 | 21 |
| 4 | 22 |
+----+-----+
And the result would be:
+----+------+
| ID | Name |
+----+------+
| 1 | A |
| 2 | B |
| 4 | D |
+----+------+
How can I do this in VLOOKUP? Or is there a better way to do this besides VLOOKUP?
Thanks.

You can acheive this result using Microsoft Query.
First, select Data > From other sources > From Microsoft Query
Then select "Excel Files*".
In the "Select Workbook" windows, you have to select the current Workbook.
Next, in the query Wizard windows, select sheet1$ and sheet2$ and click the ">" button.
Click Next and the query visual editor will open.
Click on the SQL button and paste this query :
SELECT `Sheet1$`.ID, `Sheet1$`.Name, `Sheet2$`.Age
FROM`Sheet1$`, `Sheet2$`
WHERE `Sheet1$`.ID = `Sheet2$`.ID
Finally close the editor and put the table where you need it.
The result should look like this :

First lets get a list of values that exist in both tables. If you are using excel 2010 or later then in Sheet 3 A2 put the following formula:
=IFERROR(AGGREGATE(15,6,Sheet2!$A$1:$A$5000/(COUNTIF(Sheet1!$A$1:$A$5000,Sheet2!$A$1:$A$5000)>0),ROW(1:1)),"")
If you are using 2007 or earlier then use this array formula:
=IFERROR(SMALL(IF(COUNTIF(Sheet1!$A$1:$A$5000,Sheet2!$A$1:$A$5000),Sheet2!$A$1:$A$5000),ROW(1:1)),"")
Being an array formula, copy and paste into the formula bar then hit Ctrl-Shift-Enter instead of Enter or Tab to leave the edit mode.
Then copy down as many rows as desired. This will create a list of ID'd that are in both lists. This does assume that ID is a number and not text.
Then with that list we use vlookup:
=IF(A2<>"",VLOOKUP(A2,Sheet1!A:B,2,FALSE),"")
This will then return the value from Sheet 1 that matches.

For Basic Excel Join without formuales or Excel Macros. Please check the website
http://exceljoins.blogspot.com/2013/10/excel-inner-join.html
Joins can Left Outer, Right Outer and Full Outer which used in rare ocassions, But we can achieve this for Excel Sheets, For more information check the below
http://exceljoins.blogspot.com/

Related

Sql Server how to find values in different tables that have different suffix

I'm struggling to find a value that might be in different tables but using UNION is a pain as there are a lot of tables.
[Different table that contains the suffixes from the TestTable_]
| ID | Name|
| -------- | -----------|
| 1 | TestTable1 |
| 2 | TestTable2 |
| 3 | TestTable3 |
| 4 | TestTable4 |
TestTable1 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 20 |
TestTable2 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------------------|
| 1 | brazilian_goose | withFeather? |featherID |
| 2 | annoying_rooster | withoutFeather?|shinyfeatherID |
| 3 | annoying_rooster | no_legs? |dead |
TestTable3 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 15 |
Common columns: q1 and a1
Is there a way to parse through all of them to lookup for a specific value without using UNION because some of them might have different columns?
Something like: check if "q1='age'" exists in all those tables (from 1 to 50)
Select q1,*
from (something)
where q1 exists in (TestTable_*)... or something like that.
If not possible, not a problem.
You could use dynamic SQL but something I do in situations like this where I have a list of tables that I want to quickly perform the same actions on is to either use a spreadsheet to paste the list of tables into and type a query into the cell with something like #table then use the substitute function to replace it.
Alternative I just paste the list into SSMS and use SHIFT+ALT+ArrowKey to select the column and start typing stuff out.
So here is my list of tables
Then I use that key combo. As you can see my cursor has now selected all those rows.
Now I can start typing and all rows selected will get the input.
Then I just go to the other side of the table names and repeat the action
It's not a perfect solution but it's quick a quick and dirty way of doing something repetitive quickly.
If you want to find all the tables with that column name you can use information schema.
Select table_name from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME = 'q1'
Given the type of solution you are after I can offer a method that I've had to use on legacy systems.
You can query sys.columns for the name of the column(s) you need to find in N tables and join using object_id to sys.tables where type='U'. This will give you a list of table names.
From this list you can then build a working query for each table, and depending on your requirements (is this ad-hoc?) either just manually execute it yourself of build a procedure that will do it for you using sp_executesql
Eg
select t.name, c.name
into #workingtable
from sys.columns c
join sys.tables t on t.object_id=c.object_id
where c.name in .....
psudocode:
begin loop while rows exist in #working table
select top 1 row from #workingtable
set #sql=your query specific to that table and column(s)
exec(#sql) / sp_executesql / try/catch as necessary
delete row from working table
end loop
Hopefully that give ideas at least for how you might implement your requirements.

How do I access a new cell created by Cell(i,j).Split in Powerpoint VBA

Assume I have a table in Powerpoint which looks the left table in this illustration. Straight forward, two columns, two rows.
___________________ ___________________
| | | | | |
| 1,1 | 1,2 | Split | 1,1 | 1,2 |
| | | | | |
|_________|_________| -----> |_________|_________|
| | | -----> | | ?,? |
| 2,1 | 2,2 | | 2,1 |_________|
| | | | | ?,? |
|_________|_________| |_________|_________|
I have access to the shape holding the table via the following variable
dim myShape As PowerPoint.Shape
I can access the lower right cell using (remember that VBA cells are 1-based, not zero-based)
myShape.Table.Cell(2,2)
I can split any cell. Let's split the lower right cell into 2 rows:
myShape.Table.Cell(2,2).Split 2,1
my table now looks like the right one of the two tables at the top.
How would I access any of the two cells in the lower right corner, indicated by ?,??
I have tried
myShape.Table.Cell(2,2).Shape.Table.Cell(1,1)
for example, to access the upper of these two cells. I have also inspected the respective vba-objects in the vba debugger and did some google research. All I was able to find was how to split cells, not how to access any cells after splitting. How can I do this?
Once you split a cell, PowerPoint thinks there are more rows (or columns, if you split that way). The first statement would access the top cell of the split, the second statement the lower one:
ActivePresentation.Slides(1).Shapes(1).Table.Cell(Row:=2, Column:=2).Select
ActivePresentation.Slides(1).Shapes(1).Table.Cell(Row:=3, Column:=2).Select

MS Access String Replacement Query

I have 2 tables, Table1 and Table2. I need to replace a string or a series of strings (separated by commas) in Table1 referred from Table2.
I did a query on this but no luck:
TableNew: Iif(Instr([Table1.ColumnX1],[Table2.ColumnY1],Replace([Table1.ColumnX1],[Table2.ColumnY1],[Table2.ColumnY2]),[Table1.ColumnX1])
What i wanted to achieve was like this, in Table1 ColumnX1 there is:
A,B,C,1,2,3,4,D,E,F,5,6
Then in Table2 I have:
+----------+-----------+
| ColumnY1 | ColumnY2 |
+----------+-----------+
| A | Z |
| B | Y |
| C | X |
| D | W |
| E | V |
| F | U |
+----------+-----------+
After running that Query, it would result to
Z,Y,X,1,2,3,4,W,V,U,5,6
I would like this to run in each row available in Table1.
Thanks in advance.
You can use a query such as the following to modify the values held by Table1:
update table1 inner join table2 on instr(1, table1.columnx1, table2.columny1) > 0
set table1.columnx1 = replace(table1.columnx1, table2.columny1, table2.columny2)
Note that the joins implemented in the above query cannot be displayed by the MS Access query designer, however, it is valid SQL which may be successfully executed by the JET database engine used by MS Access.

Need alternate SQL

I am currently working with an H2 database and I have written the following SQL, however the H2 database engine does not support the NOT IN being performed on a multiple column sub-query.
DELETE FROM AllowedParam_map
WHERE (AllowedParam_map.famid,AllowedParam_map.paramid) NOT IN (
SELECT famid,paramid
FROM macros
LEFT JOIN macrodata
ON macros.id != macrodata.macroid
ORDER BY famid)
Essentially I want to remove rows from allowedparam_map wherever it has the same combination of famid and paramid as the sub-query
Edit: To clarify, the sub-query is specifically trying to find famid/paramid combinations that are NOT present in macrodata, in an effort to weed out the allowedparam_map, hence the ON macros.id != macrodata.macroid. I'm also terrible at SQL so this might be completely the wrong way to do it.
Edit 2: Here is some more info about the pertinent schema:
Macros
| ID | NAME | FAMID |
| 0 | foo | 1 |
| 1 | bar | 1 |
| 2 | baz | 1 |
MacroData
| ID | MACROID | PARAMID | VALUE |
| 0 | 0 | 1 | 1024 |
| 1 | 0 | 2 | 200 |
| 2 | 0 | 3 | 89.85 |
AllowedParam_Map
| ID | FAMID | PARAMID |
| 0 | 1 | 1 |
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 4 |
The parameters are allowed on a per-family basis. Notice how the allowedParam_map table contains an entry for famid=1 and paramid=4, even though macro 0, aka "foo", does not have an entry for paramid=4. If we expand this, there might be another famid=1 macro that has paramid=4, but we cant be sure. I want to cull from the allowedParam_map table any unused parameters, based on the data in the macrodata table.
IN and NOT IN can always be replaced with EXISTS and NOT EXISTS.
Some points first:
You are using an ORDER BY in your subquery, which is of course superfluous.
You are outer-joining a table, which should have no effect when asking for existence. So either you need to look up a field in the outer-joined table, then inner-join it or you don't, then remove it from the query. (It's queer to join every non-related record (macros.id != macrodata.macroid) anyway.
You say in the comments section that both famid and paramid reside in table macros, so you can remove the outer join to macrodata from your query. You get:
As you say now that famid is in table macros and paramid is in table macrodata and you want to look up pairs that exist in AllowedParam_map, but not in the aformentioned tables, you seem to be looking for a simple inner join.
DELETE FROM AllowedParam_map
WHERE NOT EXISTS
(
SELECT *
FROM macros m
JOIN macrodata md ON md.macroid = m.id
WHERE m.famid = AllowedParam_map.famid
AND md.paramid = AllowedParam_map.paramid
);
You can use not exists instead:
DELETE FROM AllowedParam_map m
WHERE NOT EXISTS (SELECT 1
FROM macros LEFT JOIN
macrodata
ON macros.id <> macrodata.macroid -- I strongly suspect this should be =
WHERE m.famid = ?.famid and m.paramid = ?.paramid -- add the appropriate table aliases
);
Notes:
I strongly suspect the <> should be =. <> does not make sense in this context.
Replace the ? with the appropriate table alias.
NOT EXISTS is better than NOT IN anyway. It does what you expect if one of the value is NULL.

SQL - Selecting all latest unique records

I'm struggling a bit at creating an SQL query to select some records from an Access Database (using Excel VBA).
A cut of one of the tables (let's call it 'table1') has the following columns:
| my_id | your_id | phase |
| 1 | 1 | Open |
| 2 | 1 | Close |
| 3 | 2 | Open |
| 4 | 3 | Close |
| 5 | 2 | Close |
| 6 | 3 | Open |
The field 'my_id' will always be a unique value whereas the 'your_id' field may contain duplicates.
What I would like to do is select everything from the table for the most recent record of the 'your_id' where the phase is 'Close'. So that means in the above example table it would select 5, 4 & 2.
Hope this makes sense, sorry if not - I'm struggling to articulate what I mean!
Thanks
Although from ur example if u just add where conditin as phase='Close' u will get the records of 5,4 and 2. But I am assuming that there might be scenarios (not in ur example) where more than 1 record can come with status as Close for any given your_id so query should look like this
Select * from table1 where my_id in (
Select Max(My_Id) from table1 where phase='Close' group by your_id)