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

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.

Related

Run two select statements in one view?

I have some SQL that is broken into two SELECT statements. The first SELECT statement inserts results INTO a temp table. The second SELECT statement is a COALESCE that reads data from the temp table the first one inserted data into. I need to be able to run these together (one after the other) and unfortunately cannot put these into a Stored Procedure due to the old reporting tool my company uses. The reporting tool must read from a VIEW or a TABLE. I wanted to put these into a VIEW, but have researched that a view cannot have more than one SELECT. Any ideas and examples on how to accomplish this? My original post/solution showing the SQL is in this post.
The temp table select could be converted to be a CTE (With clause), and the 2nd part the select query of the view.
Alternatively you could just inline it with sub-selects, but depending on complexity that might make it harder to maintain.
CREATE VIEW yourView AS
WITH myFirstSelect(someFields) AS
(
SELECT somefields FROM sometable
)
SELECT * from myFirstSelect
Docs : https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-2017

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.

DB2 With Clause

I am new to DB2 and I have a question about the with clause.
For example in the following query:
WITH values AS
(
SELECT user_id, user_data FROM USER WHERE user_age < 20
)
SELECT avg(values.user_data) FROM values
UNION
SELECT sum(values.user_data) FROM values
How many times will the common table expression be executed? Will the result of the with clause be stored in a temporary table or it will do sub-select twice.
(I use with and union here just to give an example, and sorry for my poor english)
As #Vladimir Oselsky has mentioned, only looking at the execution plan will give you a definite answer. In this contrived example the CTE subselect will likely run twice.
In DB2, common table expressions should create the Common Table Expression Node in the execution plan (see the documentation here). This node explicitly says:
They serve as intermediate tables. Traditionally, a nested table
expression also serves this purpose. However, a common table
expression can be referenced multiple times after it is instantiated;
nested table expressions cannot.
I read this as saying that the CTE is only evaluated once, instantiated, and then used multiple times. Also, if the CTE is referenced only one time, the "instantiation" is optimized away.
Note that this is the way that Postgres handles CTEs (materialized subqueries) and not the way the SQL Server handles them.

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 ...