Creating #temp before CTE SQL Server 2012 - sql

I need to create a #temp table before my list of CTE:s start so that I can use it in the end to perform calculations.
This is what I have written so far:
SELECT DISTINCT
SUM(X+Y) AS Total
INTO #Summary
FROM Table
WITH CTE_START AS
(
SELECT DISTINCT *
FROM TableX
)
....
I have even tried creating my #Summary as a CTE and then writing INTO before FROM. It does not work.
I have looked at similar questions on:CTE&Temp Table
I have not found anything helpful. How can I create a #temp table before my WITH CTE_START begins processing?

You need to terminate the statement before the CTE with a semicolon, otherwise SQL Server doesn't know the WITH isn't part of the previous statement, for example part of a table hint.
For example:
SELECT DISTINCT SUM(X+Y) AS Total INTO #Summary FROM Table;
WITH CTE_START AS ( SELECT DISTINCT * FROM TableX )
SELECT * FROM CTE_START

Related

Should I Use a Temp Table To Optimize?

I have a somewhat complex query that I need to access for the IDs in order to delete from multiple tables, something along the lines of:
DELETE FROM Table1 WHERE ID IN ( -- Query here -- )
DELETE FROM Table2 WHERE ID IN ( -- Query here -- )
Would selecting the query into a temp table be more efficient than writing out the entire query twice, or is it just visually cleaner?
SELECT ( -- Query here -- ) INTO #Temp
DELETE FROM Table1 WHERE ID IN ( SELECT * FROM #Temp )
DELETE FROM Table2 WHERE ID IN ( SELECT * FROM #Temp )
Also, am open to other suggestions that I may have overlooked.
Thanks in advance
Completely agree with Jeroen Mostert. Try it and see. You could although try to use CTE for deletion or table variables and select distinct values of IDs there in case you have no distinct values of IDs in your query. And if you have a lot of data to delete, try to create additional indexes in temp table.

How to add union data in table?

Thanks in advance !!
I want to get below data in separate table with column how can we achieved this.
From my reading of your question, you would like the results of that SELECT statement put into a new table?
Firstly, I'm assuming your original SQL works as a SELECT statement - e.g., all those tables have the same structure. Note that you can simplify the unions, but I haven't done so here, to keep the key part of the answer (saving the data) as the main focus.
To save the data into another table, you can either create a table first and make that into an insert, or just use 'SELECT INTO' within the main SELECT.
If you are happy with the columns being automatically created, the 'SELECT INTO' version will create columns (e.g., you do not need to specify the columns in a CREATE TABLE statement). However, when you run the SELECT INTO, it does create the table. Therefore if you want to insert further values, you need to specify the column list (or have matching column lists).
SELECT INTO version
select *
INTO #Temp -- Added This row
from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
INSERT INTO version
CREATE TABLE #Temp (<your fields here to match the SELECT statement>)
INSERT INTO #Temp
select * from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
Set operators are evaluated from top to bottom so there only needs to be 1 subquery. Something like this
select ab.* into #Temp
from (select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
except
select * from #ONEYRCON
except
select * from #OTHERYRCON) ab;

Sql Server Issue During Update

Hello I am little bit confused to see the sql server behaviour on executing the query. According to mine the output should be "Priyanka" ,4
Declare #temp table(
Name Varchar(50),
amount int
)
insert #temp values ('Priyanka' ,10 )
Update #temp
set amount=amount-A.a
from (
select 'Priyanka' as Name,1 as a
union
select 'Priyanka' as Name,5 as a
)A
where [#temp].Name in (A.Name)
select * from #temp
But
the output
Name amount
Priyanka 9
Can any one Please tell me why this is happened.
Standard SQL doesn't support a from clause with update and you'd instead have to write your access to other tables as a direct subquery in the set clause. If you did that, you'd get the error "subquery returned more than one value" and have some idea of the issue.
Unfortunately, the Microsoft extension to SQL that allows a FROM clause also silently ignores the fact that multiple rows may match, uses one of those rows and ignores the others.1
If you're going to use this extension, it's up to you to carefully ensure that you don't have multiple matches to a single row in the target table.
I'd rearrange your query, something like:
Declare #temp table(
Name Varchar(50),
amount int
)
insert #temp values ('Priyanka' ,10 )
;With A as
(
select 'Priyanka' as Name,1 as a
union
select 'Priyanka' as Name,5 as a
)
Update t
set amount=amount-Aa.a
from
#temp t
cross apply
(select SUM(a) as a from A where Name = t.Name) Aa
select * from #temp
Where I use the cross apply to aggregate the data down to a single row per target row.
1Importantly, though, it does support the concept that the effects of an UPDATE are applied "as if" all rows (and columns within them) are updated in parallel. So you don't get that first the update applies using one row and then the second update gets to update an already updated row.
You need to SUM the values of the union entries. Simply UNION the entries it have multiple entries so it may take any one entry and ignore the remains.
For your case the following query will work:
DECLARE #temp TABLE (NAME VARCHAR(50), amount INT)
INSERT #temp
VALUES ('Priyanka', 10)
UPDATE t
SET amount = t.amount - A.a
FROM #temp t
JOIN (
SELECT NAME, SUM(a) AS a FROM (
SELECT 'Priyanka' AS NAME, 1 AS a
UNION
SELECT 'Priyanka' AS NAME, 5 AS a
) c
GROUP BY NAME
) A ON A.NAME = t.NAME
SELECT * FROM #temp

CTE inside CTE in SQL Server

Please don't mark this question as duplicate of CTE within a CTE .. I checked that question and answer ... but that answer does not satisfy my need.
I want to run Nested CTE query like this
Drop Table #Temp
Create Table #Temp(name1 text, name2 text)
Insert INTO #Temp Values ('test','test')
Insert INTO #Temp Values ('test','test')
;WITH CTE1 AS (
With CTE2 as ( Select * from #Temp)
)
Select * from CTE1
or
;WITH CTE1 AS (
Select * From (With CTE2 as ( Select * from #Temp))
)
Select * from CTE1
In our structure... the inner CTE2 query have been provided by other system .. so I can't control
inner part of the query... so.. here my duty is only select values from inner query and form new CTE in my system ...
And please imagine this
;WITH CTE1 AS (
"Query Provide by Other System"
)
In some cases the "Query Provide by Other System" start with CTE..this may or may not be the CTE query... that is the exact problem for I can't use like below
;WITH CTE1 AS (
Select * From
)
,With CTE2 as
( Select * from #Temp))
pls help anyone to prcoeed this, I guess my need is too dynamic
Just to have an idea:
;WITH cte1 AS
(
SELECT * FROM ...
),
cte2 as
(
SELECT * FROM ...
),
cte3 as
(
SELECT * FROM ... INNER JOIN cte2 ON...
),
SELECT *
FROM
cte1
INNER JOIN cte3 ON ...
Separate your CTEs with ,s rather than nesting them.
;
WITH
CTE2 AS
(
SELECT * FROM #Temp
)
,
CTE1 AS
(
SELECT * FROM CTE2
)
SELECT
*
FROM
CTE1
EDIT : Following your additional comments
As I understand it, you are being provided with a system generated query that you then want to embed in another query. Sometimes that system generated query uses a CTE, sometimes it doesn't; you don't know in advance the format of that query.
Unfortunately for you this means that you can not embed this within another CTE.
One option could be to use real views.
CREATE VIEW xxx AS
<system generated code here>
;
SELECT
*
FROM
xxx
;
You do then, however, have to be very careful about concurrency; two concurrent users trying to create the same view with the same name.
The better solution would be to approach the vendor of the system with is creating the system generated query and ask them how they propose you use it.
;with BASE AS (
SELECT * FROM table1
), BASE2 AS (
SELECT * from table2
), BASE3 AS (
SELECT * FROM table3
) SELECT * FROM BASE INNER JOIN BASE3 ...
I guess this is what you are trying to do.
If your system generated query uses db qualified object names you can hack this by using OPENQUERY:
WITH CTE AS
( SELECT *
FROM OPENQUERY([Your Server], 'Query Provide by Other System')
)
SELECT *
FROM CTE;
You may need to configure your server for data access:
EXEC sp_serveroption 'your server', 'DATA ACCESS', TRUE;

Can use select into with multiple cte

Can use select into with multiple cte? for example in the below code the result of the first cte cte_table is inserted into dbo.table1, then the other cte is defined. is this possible?
WITH cte_table
AS
(
SELECT *
FROM dbo.table
)
INSERT INTO dbo.table1
SELECT *
FROM [cte_table]
, cte_table2
AS
(
SELECT *
FROM dbo.table2
)
Chain all your CTEs and THEN do the select into.
WITH First_CTE AS
(
SELECT
Columns
FROM
Schema.Table
WHERE
Conditions
),
Second_CTE AS
(
SELECT
Columns
FROM
Schema.OtherTable
WHERE
Conditions
)
SELECT
Variables
INTO
NewTable
FROM
First_CTE A
JOIN
Second_CTE B
ON
A.MatchVar = B.MatchVar
This can be helpful if you have no need of the CTEs later but prefer a simpler method than subqueries for your ETL.
If your case is Re-usability of the record set, in that case use a Temp Table or Table variable.
e.g.
Select * Into #temp1 From dbo.table
INSERT INTO dbo.table1
SELECT * FROM #temp1
SELECT * FROM #temp1 ..... and do some other re-usability operations.
A chained Cte work as under (just an example)
;With Cte1 As ( Select * from table1)
,Cte2 As (Select * from table2)
select c1.*,c2.*
from cte1 c1, cte2 c2
Hope you understand when to use what and how.
No you can't: you get an error as INTO is not allowed, and, as others have pointed out, it makes sense as the CTE is intended to be a repeatable (and thereby static) reference.
And I recall reading somewhere that is/was in large part syntactical sugar, in so far as the cte is resolved out into a derived table when the sql is executed.
No You cant use select into in CTE. And it actually does not make any sense also.