Why Common table expression does not work with INSERT SELECT - sql

I am trying to use a common table expression in my INSERT.
When I do:
with A as (select col1,col2 from table1) select * from A
it works
But when I do:
with A as (select col1,col2 from table1)
insert into table2 (col1,col2) (select col1,col2 from A)
I get:
found "INSERT" (at char XXXXX) expecting `SELECT' or `'(''

Your query should work with most databases. However, Oracle and earlier versions of Postgres put the CTE next to the select. So, if you are using Oracle, earlier versions of Postgres or Postgres-derived databases:
insert into table2 (col1, col2)
with A as (select col1, col2 from table1)
select col1, col2 from A;
Also, there is no need for parentheses around the select query. It isn't a subquery.

Related

BigQuery: Use COUNT as LIMIT

I want to select everything from mytable1 and combine that with just as many rows from mytable2. In my case mytable1 always has fewer rows than mytable2 and I want the final table to be a 50-50 mix of data from each table. While I feel like the following code expresses what I want logically, it doesn't work syntax wise:
Syntax error: Expected "#" or integer literal or keyword CAST but got
"(" at [3:1]
(SELECT * FROM `mytable1`)
UNION ALL (
SELECT * FROM `mytable2`
LIMIT (SELECT COUNT(*) FROM`mytable1`)
)
Using standard SQL in bigquery
The docs state that LIMIT clause accept only literal or parameter values. I think you can ROW_NUMBER() the rows from second table and limit based on that:
SELECT col1, col2, col3
FROM mytable1
UNION ALL
SELECT col1, col2, col3
FROM (
SELECT col1, col2, col3, ROW_NUMBER() OVER () AS rn
FROM mytable2
) AS x
WHERE x.rn <= (SELECT COUNT(*) FROM mytable1)
Each SELECT statement within UNION must have the same number of
columns
The columns must also have similar data types
The columns in each SELECT statement must also be in the same order
As your mytable1 always less column than mytable2 so you have to put same number of column by selection
select col1,col2,col3,'' as col4 from mytable1 --in case less column you can use alias
union all
select col1,col2,col3,col4 from mytable2

SQL: How to combine count results from multiple tables into multiple columns

I have two tables that are the same in their structure, but all I really want out of them is a distinct count from a single row from each into a multi-column result set.
I keep getting syntax errors, but so far haven't been able to get something that delivers the data I want, and makes it through the parser. I'm trying to figure out if this is a SQL problem (possible given that I'm using a website's implementation, rather than native MySQl/SQL/Oracle) or a me problem (much more likely).
So what I want is two unrelated (and un-primary-keyed) tables to return a COUNT(DISTINCT column) into a single result. I have tried a couple of different approaches:
select 1,2 FROM
(SELECT COUNT(DISTINCT col1) as 1 from table1),
(SELECT COUNT(DISTINCT col2) as 2 from table2)
SELECT *
FROM (
SELECT COUNT(DISTINCT col1) AS 1
FROM table1
)
CROSS JOIN (
SELECT COUNT(DISTINCT col2) AS 2
FROM table2
)
I have also messed around with 4-5 different uses of union || union all to no avail. Curious what thoughts someone more schooled in the arts of SQL might have. Thanks.
Depending on the database RDBM you are, a few things could change in syntax. In the ANSI Sql definition your query should be:
select col1, col2 FROM
(SELECT COUNT(DISTINCT col1) as col1 from table1) as tab1,
(SELECT COUNT(DISTINCT col2) as col22 from table2) as tab2
You have to add alias for all sub queries. Also name your columns with words, not number, it is easier to understand. Though I don't recall if a number is not allowed as an alias in SQL ANSI.
Without aliases for the subqueries you can use like this:
-- For MySql, PostgreSql, SQL Server (not sure though)
select (SELECT COUNT(DISTINCT col1)
from table1) as col1,
(SELECT COUNT(DISTINCT col2) as col22
from table2) as col2
-- For Oracle
select (SELECT COUNT(DISTINCT col1)
from table1) as col1,
(SELECT COUNT(DISTINCT col2) as col22
from table2) as col2
from dual
-- For DB2
select (SELECT COUNT(DISTINCT col1)
from table1) as col1,
(SELECT COUNT(DISTINCT col2) as col22
from table2) as col2
from sysibm.sysdummy1
Side note: you can use a number as an alias if you surround it with double quotes " (this is SQL ANSI and will work everywhere) like this:
select "1", "2" FROM
(SELECT COUNT(DISTINCT col1) as "1" from table1) a, --don't forget the table alias
(SELECT COUNT(DISTINCT col2) as "2" from table2) b
Mysql Also allows you to use back ticks:
select `1`, `2` FROM
(SELECT COUNT(DISTINCT col1) as `1` from table1) a,
(SELECT COUNT(DISTINCT col2) as `2` from table2) b

SELECT INTO with HSQLDB

I am trying to create a new table from the result of a select. This works fine with SQL Server:
SELECT * INTO newTable FROM (SELECT col1, col2, col3 FROM oldTable) x;
Now, I want to achieve the exact same thing with HSQLDB (Version 2.2). I have tried several forms like
SELECT * INTO newTable FROM (SELECT col1, col2, col3 FROM oldTable);
SELECT INTO newTable FROM SELECT col1, col2, col3 FROM oldTable;
CREATE TABLE newTable AS SELECT col1, col2, col3 FROM oldTable;
All these variants result in some form of syntax error. How can I create a table from a select with HSQLDB?
The manual has an example for this:
CREATE TABLE t (a, b, c) AS (SELECT * FROM atable) WITH DATA
HSQLDB requires parentheses around the select (unlike all other DBMS) and it also requires the WITH DATA clause
Ok I found very easier way to do this.
select * into t_bckp FROM t;
Its interesting.

SQL "In" Statement Match Anything

If I have a query like this
SELECT * FROM table1 WHERE col1 IN ({SUBS})
Is there anything I can replace {SUBS} with that will return all rows in the table?
Further details:
I am building the SQL dynamically in my app, so I cannot (should not) edit other parts of the query except what's in braces. So,
SELECT * FROM table1
will not do.
Also,
SELECT * FROM table1 WHERE col1 IN (SELECT col1 FROM table1)
would be hackish and highly inefficient. Consider the table have more than 50k rows.
This would do it:
select col1 from table1
Edit: There seems to be a bit of confusion - the OP asked what value could be used to replace {SUBS} that would return all rows from table1. My answer above is what you could use in place of {SUBS} that would return all the rows.
This works for me in SQL Server:
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN (COLUMN_NAME)
Have you tried just using COL1 for {SUBS}?
e.g.
SELECT * FROM table1 WHERE col1 IN (col1)
If you replaced {SUBS} with SELECT col1 FROM table1, you would end up with
SELECT * FROM table1 WHERE col1 IN (SELECT col1 FROM table1);
which would return all rows from table1. This is, of course, simply a more roundabout way of saying:
SELECT * FROM table1;
You're right,
SELECT * FROM table1 WHERE col1 IN (SELECT col1 FROM table1)
does work, but is highly inefficient; requiring a merge join to return all rows.
Use the following which is just as efficient as regular SELECT * FROM table1
SELECT * FROM table1 WHERE col1 IN (col1)
However, that said; I suggest you have a chat to the person who is trying to impose the SELECT * FROM table1 WHERE col1 IN ({SUBS}) structure. There is no good reason to do so.
It unnecessarily complicates queries.
Creates risk of highly inefficient queries.
Potentially even limits developers to use certain techniques.
I suspect the person imposing this is trying to implement some sort of silver-bullet framework. Remember, the golden rule in software development is that there are no silver-bullets.
If you're simply trying to retrieve every row in the table, then:
select * from table1
If you're trying to prove a point or win a bet or something, then:
select * from table1 where col1 in (select col1 from table1)
If the query requires some WHERE condition, then I would try to replace it with an EXISTS statement:
select
*
from
table1 t1
where
exists ( {subs} )
Then {subs} can be replaced with any expression that does not yield NULL.
This works in Oracle:
select * from table1 where col1 in (col1)

join two tables into one big table

I have two tables with the same columns, and I need to copy one table's rows to the other table's rows to create one big table with all the values from both tables. Right now I am doing this query to return the same thing:
SELECT col1, col2, col3 from Table1
union
SELECT col1, col2, col3 from Table2
However, it seems horribly inefficient, and on my system is very slow (returns 1210189 records).
May it work to just do:
SELECT col1, col2, col3
INTO Table1
FROM Table2
Start with union all:
select col1, col2, col3 from Table1
union all
select col1, col2, col3 from Table2
Your query is trying to deduplicate things, which would slow it down considerably.
I think the best option is to create a view in sql server, this will optimize the performance of the query:
SELECT col1, col2, col3 from Table1
union all
SELECT col1, col2, col3 from Table2
(As other users said: "union" is used to select distinct values from two tables
where as "union all" is used to select all values including
duplicates from the tables.)
At the same time I would restrict the number of rows I get from the database if i am writing them for a web and if this is giving me problems, with the new functions of Sql Server 2005 row_number(), with this I would page results.
You could use this to fill the second table:
Insert into table2 select * from table1;
Or if you want to be more specific:
Insert into table2(col1, col2, col3) select col1, col2, col3 from table1;
(Note: some DBMSs might require putting parenthesis around the SELECT clause.)
select * into new table(your new table name)
from table1.col1,table1.col2,table2.col1;
here columns can be your required columns .
select * into newtable from table1
union all
select * from table2
Worked well. Guidelines, both tables have exact same column names :)