I have 2 tables with the following fields.
Table1
AA
BB
CC
DD
Table2
AA
CC
EE
Query
Select t1.*,
t2.*
from table1 t1,
join table2 t2 on table1.DD = table2.EE
My data columns back with the following column names:
AA, BB, CC, DD, **AA_1**, **CC_1**, EE
I don't want the column names like that. I want them to have the table name prefixed in the names of common (or all columns). I could fix this with:
select t1.AA as t1_AA, t1.BB as t1_BB, t1.CC as t1_CC, t1.DD as t1_DD,
t2.AA as t2_AA, t2.CC as t2_CC, t2.EE as t2_EEE
from table1 t1,
inner join table2 t2
on table1.DD = table2.EE
But that means every select everywhere becomes 500 lines longer. Is there a magic way to do this in oracle? Basically I want to write my code like
select t1.* as t1_*, t2.* as t2_*
from table1 t1,
inner join table2 t2
on table1.DD = table2.EE
But of course that is not valid SQL
In Oracle SELECT syntax, there is currently no way to assign column aliases to multiple columns based on some expression. You have to assign an alias to each individual column.
Is there a magic way to do this in oracle?
Not that I'm aware of. Your options amount to:
Address the column naming scheme - you'd need to use ALTER TABLE statements like:
ALTER TABLE table_name
RENAME COLUMN old_name to new_name;
Use column aliases
You could use views to save on the work & effort of defining column aliases, but it's not a recommended practice because of the bad performance when layering views on top of one another.
Is creating a view an option?
What is the software you're using that does this to you? I don't see this behavior in SQL*Plus or PL/SQL Developer in 10g. PL/SQL won't let you build a cursor with this ambiguity in it.
Try this
select t1.AA "t1_AA", t2.AA "t2.AA"
from table1 t1,
inner join table2 t2
on table1.DD = table2.EE
As he said before, you need to do it per column
Related
Using SSMS when joining 3+ tables and using SELECT *, I'm wondering if there is an easy way (dynamic) to include the table name & column name in the result set without having to type out all the desired columns.
For example:
Table1
Table2
Table3
SELECT *
FROM Table1 t1
LEFT JOIN Table2 t2 ON t2.keyA = t1.keyA
LEFT JOIN Table3 t3 ON t2.keyB = t3.keyB
Trying to produce output like
Table1-Column1, Table2-Column1, Table3-Column1
OR
t1.Column1, t2.Column1, t3.Column1
If you have a lot of column, there's is an easy way to do it, but not dynamically. If you have only a few columns, doesn't worth a try and do it manually.
Take a look at theses two methods : https://blog.sqlauthority.com/2012/06/06/sql-server-tricks-to-replace-select-with-column-names-sql-in-sixty-seconds-017-video/
First method (drag'n'drop columns) isn't useful in your case cause we need to have all column aligned on different lines. The second (generating the create table script) is the one we need.
Generate the create table for table1 and copy-paste the columns needed from table1 into your query, and repeat for table2 and table3. Make sure they are all aligned in the same editor column.
Then, "the magic trick", simply press and hold the Alt key, click between the coma and the first letter of the first column name of t1 and drag to select the lines between the first column of t1 to the last column of t1. Type "t1.". That's it. repeat for t2 and t3.
This is not sql-server related, nor SSMS, but works with any decent editor supporting multiline editing.
It seems like sqlite3 needs additional information in terms of specifying where you want to extract certain columns from when joining two tables. Somehow, when I try to do a select statement with a join clause, the query returns:
Error: ambiguous column name: name
even though I have specified in my statement where I want the 'name' column to be retrieved from, in this case from table t1:
select name from t1 join t2 on t1.name = t2.name where beer = 'Alesmith Decadence' and nickname = 'SUP';
So does sqlite3 not understand this format or something? Or is more information needed for sqlite3 to understand this query.
When you write a query, you should learn to qualify all columns names -- with convenient table aliases. It is unclear what the right aliases are, but something like this:
select t1.name
from t1 join
t2
on t1.name = t2.name
where t2.beer = 'Alesmith Decadence' and t2.nickname = 'SUP';
Then it is clear to you, to everyone else, AND to the SQL parser exactly which columns you are referring to.
Note: You haven't shown sample data or shown the table definitions, so that above may not work because the table aliases may not be correct.
Try This
select t1.name
from t1 join t2 on t1.name = t2.name
where beer = 'Alesmith Decadence' and nickname = 'SUP';
I am working with a dataset of tables that (a) often requires joining tables together, however also (b) frequently has duplicate columns names. Any time I write a query along the lines of:
SELECT
t1.*, t2.*
FROM t1
LEFT JOIN t2 ON t1.this_id = t2.matching_id
...I get the error Duplicate column names in the result are not supported. Found duplicate(s): this_col, that_col, another_col, more_cols, dupe_col, get_the_idea_col
I understand that with BigQuery, it is better to avoid using * when selecting tables, however my data tables aren't too big + my bigquery budget is high, and doing these joins with all columns helps significantly with data exploration.
Is there anyway BigQuery can automatically handle / rename columns in these situations (e.g. prefix the column with the table name), as opposed to not allowing the query all together?
Thanks!
The simplest way is to select records rather than columns:
SELECT t1, t2
FROM t1 LEFT JOIN
t2
ON t1.this_id = t2.matching_id;
This is pretty much what I do for ad hoc queries.
If you want the results as columns and not records (they don't look much different in the results), you can use EXCEPT:
SELECT t1.* EXCEPT (duplicate_column_name),
t2.* EXCEPT (duplicate_column_name),
t1.duplicate_column_name as t1_duplicate_column_name,
t2.duplicate_column_name as t2_duplicate_column_name
FROM t1 LEFT JOIN
t2
ON t1.this_id = t2.matching_id;
Is there anyway BigQuery can automatically handle / rename columns in these situations (e.g. prefix the column with the table name), as opposed to not allowing the query all together?
This is possible with BigQuery Legacy SQL - which can be handy for data exploration unless you are dealing with data types or using some functions/features specific to standard sql
So below
#legacySQL
SELECT t1.*, t2.*
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.this_id = t2.matching_id
will produce output where all column names will be prefixed with respective alias like t1_this_id and t2_matching_id
Few questions i have here
I always see some SQL written like below (not sure if i get it right)
SELECT a.column_1, a.column_2 FROM table_name WHERE b.column_a = 'some value'
i don't quite understand the SQL written in such way. Is it similar to using object in programming, where you can define an object and variables within the object? If it is, where is the definition of a and b for the SQL above (assuming i got the query right)?
I want to make comparisons between 3 columns (say C1 C2 C3) in 3 different tables, say T1 T2 and T3. The condition is to get the values from the C1 in T1, that exists in C2 in T2, but not exists in C3 in T3. Both columns are practically the same, just that some might different or lesser records than the other columns in the other 2 tables, and i want to know what the differences are. Is the query below the right way to do it?
select distinct C1 from T1
and (C1) not in (select C2 from T2)
and (C1) in (select C3 from T3)
order by C1;
And is it possible to extend the condition if i want to include more tables into comparison using the query above?
If i were to customize the query above into something similar to the first question, is the query below the right way to do it?
select a.C1 from T1 a
and (a.C1) not in (select b.C2 from T2 b)
and (a.C1) in (select c.C3 from T3 c)
order by a.C1;
What are the advantanges of writing query in object way (like above), compared to writing it in traditional way? I feel like even if you define a table name as a variable, the variable only can be used within the query where it is defined, and cannot be extended to the other queries.
Thanks
the first point is a and b are "table aliases" (shortcut reference to the table(s) involved in THAT query) e.g.
SELECT a.column_1, a.column_2
FROM table_name_a a ------------------------------- table alias a defined here
INNER JOIN table_name_b b -------------------------- table alias b defined here
ON a.id = b.id
WHERE b.column_a = 'some value'
Your second query has a syntax issue: You need WHERE as shown in uppercase. It also has and performance implications. Distinct adds effort to a query, using IN() is really a syntax shortcut for a series of ORs (it might not scale well). But with the syntax it is valid.
select distinct C1
from T1
WHERE (C1) not in (select C2 from T2)
and (C1) in (select C3 from T3)
order by C1;
Yes (with performance reservations) you could add more tables into that comparison.
You introduce table aliases, done correctly, into your third query - but there is no real advantage in that query structure. Aside from just making code more convenient, aliases serve to distinguish between items that would be ambiguous. In my first query above ON a.id = b.id shows possible ambiguity in that 2 tables both have a field of the same name. Prefixing the field name by a table or table alias solves that ambiguity.
For your first point.
I always see some SQL written like below (not sure if i get it right)
SELECT a.column_1, a.column_2 FROM table_name WHERE b.column_a = 'some value'
This query is wrong. It should be like this -
SELECT a.column_1, a.column_2
FROM table_name a INNER JOIN --(There might be another join also like left join etc..)
table_name b
ON a.id = b.id WHERE b.column_a = 'some value'
so you noted in the above query that a and b are just table alias. Well, there are some cases you must use them, like when you need to join to the same table twice in one query.
For the second point. you can also do it like this
SELECT DISTINCT C1 FROM T1 t1
WHERE NOT EXISTS (
SELECT C2 FROM T2 t2 where t2.C2 = t1.C1)
AND WHERE EXISTS (
SELECT C3 FROM T3 t3 where t3.C3 = t1.C1)
ORDER BY C1;
Personally I prefer aliases, and unless I have a lot of tables they tend to be single letter ones.
I'm not 100% sure on this one so don't quote me, but ill give it my best shot.
I think that when alias' are used it is because if you don't use them your statement can he huge and hard to understand, here is a comparison with two SQL query's, one using alias' and the other without:
SELECT o.OrderID, o.OrderDate, c.CustomerName
FROM Customers AS c, Orders AS o
WHERE c.CustomerName="Around the Horn" AND c.CustomerID=o.CustomerID;
Without:
SELECT Orders.OrderID, Orders.OrderDate, Customers.CustomerName
FROM Customers, Orders
WHERE Customers.CustomerName="Around the Horn" AND Customers.CustomerID=Orders.CustomerID;
As you can see one looks much easier to understand and read than the other and makes your query's much smaller.
Aliases can be useful when:
There are more than one table involved in a query
Functions are used in the query
Column names are big or not very readable
Two or more columns are combined together
http://www.w3schools.com/sql/sql_alias.asp
You have to define the table aliases in the FROM clause, so:
SELECT a.column_1, b.column_1
FROM table1 a, table2 b
WHERE a.id = b.id
It should be possible to make your comparisons in the way you have written your query above, however it is also possible to make aliasing easier by using subqueries in the FROM clause ie:
SELECT tab1.id, tab2.id, tab3.id
FROM table1 as tab1,
(select * from table2)as tab2,
(select * from table3)as tab3
This way you can choose any columns from any of the tables using tab1.xxx etc. and then use the WHERE clause to say NOT IN tab2.column_1 etc...
I have two tables: table1, table2. Table1 has 10 columns, table2 has 2 columns.
SELECT * FROM table1 AS T1 INNER JOIN table2 AS T2 ON T1.ID = T2.ID
I want to select all columns from table1 and only 1 column from table2. Is it possible to do that without enumerating all columns from table1 ?
Yes, you can do the following:
SELECT t1.*, t2.my_col FROM table1 AS T1 INNER JOIN table2 AS T2 ON T1.ID = T2.ID
Even though you can do the t1.*, t2.col1 thing, I would not recommend it in production code.
I would never ever use a SELECT * in production - why?
you're telling SQL Server to get all columns - do you really, really need all of them?
by not specifying the column names, SQL Server has to go figure that out itself - it has to consult the data dictionary to find out what columns are present which does cost a little bit of performance
most importantly: you don't know what you're getting back. Suddenly, the table changes, another column or two are added. If you have any code which relies on e.g. the sequence or the number of columns in the table without explicitly checking for that, your code can brake
My recommendation for production code: always (no exceptions!) specify exactly those columns you really need - and even if you need all of them, spell it out explicitly. Less surprises, less bugs to hunt for, if anything ever changes in the underlying table.
Use table1.* in place of all columns of table1 ;)