Reputation: 7832
Let us say I have two tables with many columns so I do not want to name the column names explicitly in my query but i want to avoid duplicate names.
If I do:
CREATE TABLE new_table
SELECT a.*, b.*
FROM table1 a
INNER JOIN table2 b ON a.myID = b.myId
WHERE a.age > 10 and b.ice = 'melted'
I will get an error saying: duplicate column name myId
, I could also get more errors if more column names in a and b are the same.
How can I avoid this issue by automatically adding a prefix to all column names in a.* and b.* w/o explicitly mentioning all the column names - very tedious to do so!
Thanks!
Upvotes: 2
Views: 3931
Reputation: 30819
Unfortunately, you will have to list the columns in case table have matching column names. However, you can use information_schema
to get the column names, format those and copy paste in the query to save the pain, e.g.:
SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table';
The above query should give you comma separated column names with a.
prefix. You can then use the same query for table b, get the names out and use it in the main SELECT
query.
Update
As @Uueerdo has rightly said, you can add alias to columns as well, e.g.:
SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME, ' AS a_', COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table';
Upvotes: 3
Reputation: 4738
In my experience ORMs will run an initial DESCRIBE query so it can do this sort of stuff for you once it has the column names. But if you insist on doing it dynamically in a single query, you could do this with pure MySQL:
-- config
SET @database = 'your_database';
SET @tableA = 'table1';
SET @tableB = 'table2';
-- table alias "a" columns
SET @fieldsA = NULL;
SELECT GROUP_CONCAT(CONCAT('a.', COLUMN_NAME), ' AS ',CONCAT('`a.', COLUMN_NAME,'`')) INTO @fieldsA
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @database AND TABLE_NAME = @tableA;
-- table alias "b" columns
SET @fieldsB = NULL;
SELECT GROUP_CONCAT(CONCAT('b.', COLUMN_NAME), ' AS ',CONCAT('`b.', COLUMN_NAME,'`')) INTO @fieldsB
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @database AND TABLE_NAME = @tableB;
-- some variables for readability
SET @fields = CONCAT(' ', @fieldsA, ',', @fieldsB,' ');
SET @tableAliasA = CONCAT(' ',@database, '.', @tableA,' a ');
SET @tableAliasB = CONCAT(' ',@database, '.', @tableB,' b ');
-- generate our final query
SET @query = CONCAT('CREATE TABLE new_table SELECT', @fields,
'FROM', @tableAliasA,
'INNER JOIN', @tableAliasB,
'ON a.myID = b.myId WHERE a.age > 10 and b.ice = ''melted''');
-- finally run the query:
PREPARE stmt1 FROM @query;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
-- if you have problems with the above query, uncomment the following to get the query so you can run it separately
-- SELECT @query;
I'd strongly advise against using this sort of solution though. I'd sooner run an initial DESCRIBE query as earlier stated, then generate your query based on that. Another solution is to create a temporary table as a copy of the second table, then rename problematic columns, then proceed to join on it to produce the data you need to create your new_table. MySQL has no issues with result columns having the same name, the issue here is trying to create a table with two columns with the same name. So essentially what you're trying to do is a star select but excluding a column.
Another approach is to just select only the primary key from both:
SELECT a.myID as `aId`, b.myId as `bId`
then create your table containing only that. Then if you ever need data from a particular table, just LEFT JOIN on it to grab the information you're looking for. You can take this a step further and set up a VIEW to do this sort of thing for you. VIEWs can join tables for you and make it very easy to select whatever columns you're looking for. You can also setup multiple VIEWs as well. Also note that views behave just like tables for the purpose of joins. You can JOIN a view with a table, or you can join a view with a view, etc.
So rather than do what you're trying to do -- creating a new table with the data from two other tables -- consider whether you're actually looking for a VIEW.
Upvotes: 2