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
Related
My example is inspired by Oracle site
CREATE VIEW
-- ex1
with SAMP_V1 as (
AS SELECT COMM + BONUS as COL_SUM, COMM - BONUS as COL_DIFF
FROM SAMP.EMPLOYEE)
select * from SAMP_V1;
-- ex2
CREATE VIEW SAMP.V1 (COL_SUM, COL_DIFF)
AS SELECT COMM + BONUS, COMM - BONUS
FROM SAMP.EMPLOYEE;
select * from SAMP.V1;
The only difference I notice is that ex1 is written with one statement, while ex2 is split into two.
Also, I can use WITH to select subset of entire set, but I can do it with VIEW too.
Can it be that:
WITH does select work only once and
VIEW is an alias, hence it repeats SELECT every time it is mentioned
Thank you
A view and a with clause are certainly not the same thing.
A with clause generates an inline table (aka derived table) that exists only in the query within which it executes.
On the other hand, a view is a legitimate database object, that, in a sense, emulates a table. A view is defined by a sql query, so it is a virtual table, that can be queried just like any other database table. Under certain conditions, you can even run DML operations or views (update, delete, insert), that are applied to the underlying tables.
If you will repeativly need the same with clause, then a view is helpful to shorten your queries.
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.
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.
I have a CREATE TABLE query which can be done using two methods (create as select statement for thousands/million records):
First method:
create table as select some data minus (select data from other table)
OR
first i should create the table as
create table as select .....
and then
delete from ..where exist.
I guess the second method is better.For which query the cost is less?Why is minus query not as fast as the second method?
EDIT:
I forgot to mention that the create statement has join from two tables as well.
The minus is slow probably because it needs to sort the tables on disk in order to compare them.
Try to rewrite the first query with NOT EXISTS instead of MINUS, it should be faster and will generate less REDO and UNDO (as a_horse_with_no_name mentioned). Of course, make sure that all the fields involved in the WHERE clauses are indexed!
The second one will write lots of records to disk and then remove them. This will in 9 of 10 cases take way longer then filtering what you write in to begin with.
So if the first one actually isn't faster we need more information about the tables and statements involved.
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.