Joining a table onto itself in SQL and saving the result - sql

In SQL, I am joining a table onto itself:
SELECT * FROM table AS a
LEFT JOIN table AS b
ON a.NAME = b.NAME
So it's fetching all the rows which have the same NAME appearing in a row of the other table (will also return the same row twice!).
Let's say that I want to save the result into a temporary table, say something like:
SELECT * INTO ##temp_table FROM (
SELECT * FROM table AS a
LEFT JOIN table AS b
ON a.NAME = b.NAME
)
Oh dear. SQL says:
The column 'NAME' was specified multiple times.
Reason: SQL can only create a table if every column name is unique.
Obvious solution: give every column name in the "second table" an alias.
My problem is that the actual tables I'm working with have about 40 columns. Giving every one of those columns an alias seems like a wasteful use of time. Sure, I don't need every column so could drop some of them, but deciding which ones I require just now also seems wasteful.
Question: is there a shorthand way to rename every column? For example, can I append every column name with a _2 or an _a?

Ok, you have a query, with 2 joined tables, wich returns both tables columns (i don't care if you are joining the same table with itself).
So you have two possible results
Show both colums, with differents alias (AS)
SELECT * INTO ##temp_table FROM (
SELECT a.Name AS NameA, b.Name AS NameB FROM table AS a
LEFT JOIN table AS b
ON a.NAME = b.NAME
)
Or, if you don't want them duplicated (because the other will return two times the same name)
SELECT * INTO ##temp_table FROM (
SELECT a.Name FROM table AS a
LEFT JOIN table AS b
ON a.NAME = b.NAME
)
And what if you have more colums? Ok, you can just show one of the tables in the JOIN
SELECT * INTO ##temp_table FROM (
SELECT b.* FROM table AS a
LEFT JOIN table AS b
ON a.NAME = b.NAME
)
Sorry for my bad english! I hope this can help you!

I suggest querying sys.tables and sys.columns to get your renamed fields quickly:
SELECT c.name + '_2,' ColumnName
FROM sys.columns c
JOIN sys.tables t
ON c.object_id = t.object_id
WHERE t.name = 'YourTable'
Or you can combine with the OBJECT_ID() function:
SELECT c.name + '_2,' ColumnName
FROM sys.columns c
WHERE object_id = OBJECT_ID('YourTable')

Related

How to automatically rename column names in SELECT a.*, b.* to have ie. prefixes a_ and b_ in result column names?

I have two tables (a,b), or joining table to itself, having the same column names. (The table(s) is wide, having about hundred columns.)
Using:
SELECT a.*, b.*
FROM a LEFT JOIN b ON b.id=a.id AND b.date1=a.date2;
... works, but now if I want to make a view from it:
CREATE OR REPLACE VIEW v_test_ab AS
SELECT a.*, b.*
FROM a LEFT JOIN b ON b.id=a.id AND b.date1=a.date2;
... it cannot make a view, because there would be multiple columns with same name.
In PostgreSQL, is there any way to automatically rename the column names of a result table using given pattern?
Example something like:
CREATE OR REPLACE VIEW v_test_ab AS
SELECT a.* AS a_*, b.* AS b_*
FROM a LEFT JOIN b ON b.id=a.id AND b.date1=a.date2;
Or perhaps something like:
SELECT a.* AS generate_column_names('a_%', a.*)
, b.* AS generate_column_names('b_%', b.*)
Avoiding to need to write:
CREATE OR REPLACE VIEW v_test_ab AS
SELECT
a.id as a_id, a.date1 as a_date1, a.date2 as a_date2 -- and so on
, b.id as b_id, b.date1 as b_date1, b.date2 as b_date2 -- and so on
FROM a LEFT JOIN b ON b.id=a.id AND b.date1=a.date2;
I can of course use pattern matching search & replace in IDE-editor, but an end result looks like bloated. (The real world case I have, has four wide source tables with many same column names.)
While it is possible to wrap the creation query in an execute statement, joining the catalog to fetch the table and column names, it will be difficult to read.
Instead, the most simple and fast way would be to automatically build the list of column and to copy - paste it in your query.
As a bonus, the day someone asks to rename/alter/drop a specific column, there is a written record of its usage.
SELECT table_name || '.' || column_name || ' as a_' || column_name || ', '
FROM information_schema.columns
WHERE table_schema = 'my_schema'
AND table_name= 'my_tablename';
?column?
-------------------------
my_tablename.id as a_id,
my_tablename.title as a_title,
my_tablename.a as a_a,

SQL JOIN on Concatenated Column without CREATE TABLE

So one table has the ID broken into two parts SYMBOL and NUMBER, the table i want to join it to has the SYMBOL and NUMBER combined to form the ID
Below is what I've come up with which obviously doesn't work... what would i need to do to join on a concatenated column without doing a CREATE TABLE?
Select
concat(a.SYMBOL, ' ', a.NBR) AS 'ID',
a.Date,
b.Cost
From
Identities a
Join
Financials b
On **concat(a.SYMBOL, ' ', a.NBR) AS 'ID'** = b.ID
You don't "as" the result of a function used in a join. You only "as" something to give a column an alias in a SELECT block
Select
b.ID, -- can use b.id here because it is equal
a.Date,
b.Cost
From Identities a
Join Financials b On concat(a.SYMBOL, ' ', a.NBR) = b.ID

SQL select resultOfSelect from table

I’m a beginner to SQL and am struggling with the following:
I have two tables with the same columns except one column from table A is not a column of table B and table B has a column that table A doesn’t have. I want to copy data from
one into the other table.
I got the following SQL, that gives me the column-names of my table B:
SELECT name
FROM sys.columns
WHERE object_id = OBJECT_ID(’TABLEB’)
AND name <> COLUMNNOTINA
I want to use that select as a query:
SELECT
(SELECT name
FROM sys.columns
WHERE object_id = OBJECT_ID(’TABLEB’)
AND name <> COLUMNNOTINA), 0
FROM
TABLEA
This does not work, but how do I make this work?
Thank you in advance!
Let's say there is some common thing connecting the two tables
For example, ORDINAL_POSITION
T1.ORDINAL_POSITION = T2.ORDINAL_POSITION
Is there a description or property to compare each column?
select * from (
(SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(’TABLEA’) ) as T1
Inner join
(SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(’TABLEB’) ) as T2
ON T1.ORDINAL_POSITION = T2.ORDINAL_POSITION
)
Where T1.ColName <> T2.ColName

Include table name in column from select wildcard sql

Is it possible to include table name in the returned column if I use wildcard to select all columns from tables?
To explain it further. Suppose I want to join two tables and both tables have the column name “name” and many other columns. I want to use wildcard to select all columns and not explicitly specifying each column name in the select.
Select *
From
TableA a,
TableB b
Where
a.id = b.id
Instead of seeing two column with same name "name", could I write a sql to return one column name as "a.name" (or TableA.name) and one as "b.name"(or TableB.name) without explicitly putting the column name in select?
I would prefer a solution for mssql but other database could be a reference too.
Thanks!
You can use select a.*, ' ', b.* from T1 a, T2 b to make it more visible where columns from T1 end and columns from T2 begin.
You are basically joining two tables on the ID field, so you will only see one column labeled "ID", not two, because you are asking to see only those records where the ID is the same in table a and table b: they share the same id.
Try ...
SELECT 'TableA' AS 'Table', A.* FROM TableA A
WHERE A.id IN (SELECT id FROM TableB)
UNION
SELECT 'TableB' AS 'Table', B.* FROM TableB B
WHERE B.id IN (SELECT id FROM TableA)
ORDER BY id, [Table]

Updating a column in one table through a column in another table

I have 2 tables 'A' and 'B'. Both have a common column 'name' and linked with each other by a column 'id'. The column 'name' in the table A is empty whereas it has data in table B. My task is to fill all the data in that column from table B to table A with corresponding ids.
I'm using the following query:
UPDATE A
SET A.name = (SELECT B.name from B WHERE A.id = B.id)
WHERE EXISTS
(SELECT B.name from B)
As soon as I run the query in SQL developer, it just freezes and i have to force close it. Can anyone tell me what's wrong with the query?
Try this one instead:
UPDATE A
SET A.name = (SELECT B.name FROM B WHERE B.id = A.id AND B.name IS NOT NULL)
WHERE a.name IS NULL;
Since you're using Oracle, here's the reference for IS NOT NULL.
Here's the SQL Fiddle so that you can play with it: http://sqlfiddle.com/#!4/a5ad0/3
I'm not sure from the above conversation whether you made any changes beyond indexing your data, but you should include a WHERE EXISTS clause as mentioned. The complete query should look like this:
UPDATE A
SET A.name = ( SELECT B.name FROM B WHERE B.id = A.id )
WHERE EXISTS ( SELECT 1 FROM B WHERE B.id = A.id )
The WHERE EXISTS clause in your original query won't do much of anything except check to see if there is at least one non-NULL value of name in B.