How to create multiple tables from same CTE? - sql

According to this post, to create a table using a CTE, the WITH cte AS clause needs to fall within the CREATE TABLE AS (CTAS) statement.
I have a CTE that I want to use to create multiple tables, and believe it'll be really inefficient to embed it multiple times in each CTAS statement.
Is there a way to re-use my CTE to create multiple tables?

Related

Creating stored procedure with multiple temp tables

So I created a report that essentially runs a DML statement built off multiple volatile tables. The way I built it was that each of my temp tables would essentially derive off the prior. For example, in my first table I define the 'dataset' while my other temp tables defining my "exclusions", then my last couple temp table combines it all and then executes it in a final query.
I want to automate this report to pull in data daily, but I'm not sure whether to create a macro or sp for it. The bigger problem with either approach, is how would I even be able to effectively utilize each temp table? I've thought about combining ALL of my tables into a GIANT (1000+ line) DML statement, but SURELY, surely there are better, easier options out there.
Any help is deeply appreciated, thanks!
Alternatively you could use Common Table Expression (CTE) instead of temp tables:
WITH cte1 AS
(
SELECT *
FROM table_1
WHERE
), cte2 AS
(
SELECT...
FROM cte2
JOIN ...
WHERE
)
...
SELECT *
FROM cte_n;
One CTE can be depend on previous one or not, you could also use recursion and combine result in final query.

PostgreSQL return select results AND add them to temporary table?

I want to select a set of rows and return them to the client, but I would also like to insert just the primary keys (integer id) from the result set into a temporary table for use in later joins in the same transaction.
This is for sync, where subsequent queries tend to involve a join on the results from earlier queries.
What's the most efficient way to do this?
I'm reticent to execute the query twice, although it may well be fast if it was added to the query cache. An alternative is store the entire result set into the temporary table and then select from the temporary afterward. That also seems wasteful (I only need the integer id in the temp table.) I'd be happy if there was a SELECT INTO TEMP that also returned the results.
Currently the technique used is construct an array of the integer ids in the client side and use that in subsequent queries with IN. I'm hoping for something more efficient.
I'm guessing it could be done with stored procedures? But is there a way without that?
I think you can do this with a Postgres feature that allows data modification steps in CTEs. The more typical reason to use this feature is, say, to delete records for a table and then insert them into a log table. However, it can be adapted to this purpose. Here is one possible method (I don't have Postgres on hand to test this):
with q as (
<your query here>
),
t as (
insert into temptable(pk)
select pk
from q
)
select *
from q;
Usually, you use the returning clause with the data modification queries in order to capture the data being modified.

Creating temporary tables in SQL

I am trying to create a temporary table that selects only the data for a certain register_type. I wrote this query but it does not work:
$ CREATE TABLE temp1
(Select
egauge.dataid,
egauge.register_type,
egauge.timestamp_localtime,
egauge.read_value_avg
from rawdata.egauge
where register_type like '%gen%'
order by dataid, timestamp_localtime ) $
I am using PostgreSQL.
Could you please tell me what is wrong with the query?
You probably want CREATE TABLE AS - also works for TEMPORARY (TEMP) tables:
CREATE TEMP TABLE temp1 AS
SELECT dataid
, register_type
, timestamp_localtime
, read_value_avg
FROM rawdata.egauge
WHERE register_type LIKE '%gen%'
ORDER BY dataid, timestamp_localtime;
This creates a temporary table and copies data into it. A static snapshot of the data, mind you. It's just like a regular table, but resides in RAM if temp_buffers is set high enough. It is only visible within the current session and dies at the end of it. When created with ON COMMIT DROP it dies at the end of the transaction.
Temp tables come first in the default schema search path, hiding other visible tables of the same name unless schema-qualified:
How does the search_path influence identifier resolution and the "current schema"
If you want dynamic, you would be looking for CREATE VIEW - a completely different story.
The SQL standard also defines, and Postgres also supports: SELECT INTO. But its use is discouraged:
It is best to use CREATE TABLE AS for this purpose in new code.
There is really no need for a second syntax variant, and SELECT INTO is used for assignment in plpgsql, where the SQL syntax is consequently not possible.
Related:
Combine two tables into a new one so that select rows from the other one are ignored
ERROR: input parameters after one with a default value must also have defaults in Postgres
CREATE TABLE LIKE (...) only copies the structure from another table and no data:
The LIKE clause specifies a table from which the new table
automatically copies all column names, their data types, and their
not-null constraints.
If you need a "temporary" table just for the purpose of a single query (and then discard it) a "derived table" in a CTE or a subquery comes with considerably less overhead:
Change the execution plan of query in postgresql manually?
Combine two SELECT queries in PostgreSQL
Reuse computed select value
Multiple CTE in single query
Update with results of another sql
http://www.postgresql.org/docs/9.2/static/sql-createtable.html
CREATE TEMP TABLE temp1 LIKE ...

Is CTE's stored (like a table) or do you create it each time you need it? (SQL Server 2005)

Never worked with MS SQL Server before and the CTE's is new to me. But it's exactly what I need in the project I just started.
Have a table that looks like
TABLE group (
'id' int,
'parentId' int,
'groupName' varchar(255)
)
So I have a dynamic page and depending on a get parameter, "Group" I want all that's below this group returned. I'm pretty sure I can manage to write the CTE for it as well as use it.
But do I create it each time I wish to use it? (basically connect to DB, run the setup for the CTE, then use a query running on this).
Or are they stored in the database once they're created and ready to be used whenever?
If they are stored, is there any command similar to sp_tables, etc to show it /them?
Cause if they're saved there probably already exist a query that does this.
A CTE is just a different way of formin a SQL expression.
Where one comment states that it "is not a view", it is fairly similar to an inline-view. The difference being that you can reference it several times in the same query, or have recursive declarations...
WITH cte AS (...) SELECT * FROM cte
is similar to
SELECT * FROM (...)
They are not, however, persisted. You can't even do the following...
WITH
cte AS
(
...
)
SELECT * INTO #temp FROM cte
SELECT * FROM cte
The SELECT INTO will work, but by the time of the second select, the CTE is out of scope...
CTE are evaluated/created/consumed at run time. They're available only to the next single SQL statement that follows after the WITH ... SELECT.
You could insert their resultset into a table variable or temp table to have their results available for a longer duration.
You may be thinking of a View.
From MSDN:
A common table expression (CTE) can be
thought of as a temporary result set
that is defined within the execution
scope of a single SELECT, INSERT,
UPDATE, DELETE, or CREATE VIEW
statement. A CTE is similar to a
derived table in that it is not stored
as an object and lasts only for the
duration of the query. Unlike a
derived table, a CTE can be
self-referencing and can be referenced
multiple times in the same query.

Delete rows from CTE in SQL SERVER

I have a CTE which is a select statement on a table. Now if I delete 1 row from the CTE, will it delete that row from my base table?
Also is it the same case if I have a temp table instead of CTE?
Checking the DELETE statement documentation, yes, you can use a CTE to delete from and it will affect the underlying table. Similarly for UPDATE statements...
Also is it the same case if I have a temp table instead of CTE?
No, deletion from a temp table will affect the temp table only -- there's no connection to the table(s) the data came from, a temp table is a stand alone object.
You can think of CTE as a subquery, it doesn't have a temp table underneath.
So, if you run delete statement against your CTE you will delete rows from the table. Of course if SQL can infer which table to upadte/delete base on your CTE. Otherwise you'll see an error.
If you use temp table, and you delete rows from it, then the source table will not be affected, as temp table and original table don't have any correlation.
In the cases where you have a sub query say joining multiple tables and you need to use this in multiple places then both cte and temp table can be used. If you however want to delete records based on the sub query condition then cte is the way to go. Sometimes you can simply use the delete statement with out a need of cte since it's a delete statement and only rows that satisfy the query conditions get deleted even though multiple conditions are used for filtering.