SQL server Temp table with joins inside other select - sql-server

I have the following structure:
Create #temp
Select ...inser...into #temp where ...
(select ... from #temp
Join tblA where ... )
UNION
(Select ... from #temp
join tblB where ... )
After build above table I need to be able to perform WHERE, JOINS, ...
Something like:
Select ... from (above statement)
join ....
where....
I don't know how of if a #temp,joins, union... can be inside other select.
OR only thing I can do is create a #Temp2 inserting with first statement result and then work with other join,where... ?
UPDATE 1:
I also trying:
With cte (query returned columns)
as
(same query I was using to build my #temp as before)
(select ... from cte
join tblA
where...)
UNION
(select ... from cte
join tblB
where...)
But Im stuck at same point in how to perform other joins, where... with above total result

Create #temp
Select ...inser...into #temp where ...
;with temp2 as
(
select ... from #temp Join tblA where ...
UNION
Select ... from #temp join tblB where ...
)
select ... from temp2
join ....
where....

Actually you can do it without temp-table:
WITH myCTE [ ( column_name [,...n] ) ]
AS
( here you define your query )
and after that you just do your Select but use CTE
Select ... from myCTE
join ....
where....
about CTE you can read Here
After Update
Select fields from myCTE join table1
Union
Select fields from myCTE join table2
Without brackets in your query

Related

Snowflake using CTE to create table

Does Snowflake allow you to create a series of CTEs then join them together at the end to create a table?
For example:
with CTE1 as ( SELECT * FROM TABLE1)
,CTE2 AS (SELECT * FROM TABLE2)
,CTE3 AS (SELECT * FROM TABLE3)
CREATE TABLE TABLE_NAME_HERE AS
SELECT * FROM CTE1 AS 1
LEFT JOIN CTE2 AS 2 ON 1.KEY = 2.KEY
LEFT JOIN CTE3 AS 3 ON 1.KEY = 3.KEY
I'm getting a unexpected 'CREATE'. error
It's an interesting one, because that CTAS (CREATE TABLE AS) form is
CREATE TABLE <name> AS <select>
and SELECT form is can have a CTE and a CTE form is
WITH <name> AS <select>
CTE can also be in sub-select given "it's just a select", thus
SELECT <columns>
FROM (
WITH cte_1 AS (
SELECT <columns>
FROM table
)
SELECT <columns>
FROM cte_1
)
which shows why the form that Lukasz shows is correct because if we add more parens
CREATE TABLE name AS (
WITH cte_1 AS (
SELECT <columns>
FROM table
)
SELECT <columns>
FROM cte_1
)
Yes, it is possible:
CREATE TABLE TABLE_NAME_HERE AS
WITH CTE1 as ( SELECT * FROM TABLE1)
,CTE2 AS (SELECT * FROM TABLE2)
,CTE3 AS (SELECT * FROM TABLE3)
SELECT * -- here should be explicit column list to avoid name duplication error
FROM CTE1 AS 1
LEFT JOIN CTE2 AS 2 ON 1.KEY = 2.KEY
LEFT JOIN CTE3 AS 3 ON 1.KEY = 3.KEY;

sql server using recrusive cte to get the level in the same group

I have a sql server table showing the IDs and their previous IDs,
create table test2 ( ID varchar(10) ,
Pre_ID varchar(10)
)
insert into test2 values ('e','d')
, ('d','c')
, ('c','b')
, ('b','a')
, ('a',null)
, ('r','q')
, ('q','p')
, ('p',null)
the table is like this:
The result should be like this:
I have successfully got the levels using a recursive cte, but could not get the correct group for them. can anyone help? Thanks.
This is my code:
with cte as (
select id, Pre_ID, level
from #temp2
where Pre_ID is null
union all
select t2.id, t2.Pre_ID, t2.level
from cte
inner join #temp2 t2
on t2.Pre_ID=cte.id
)
select * from cte
order by id
What you need to do is start with the first level and add a ROW_NUMBER to that, then join all further levels recursively:
with cte as (
select id, Pre_ID, level, row_number() over (order by ID) as grp
from #temp2
where Pre_ID is null
union all
select t2.id, t2.Pre_ID, t2.level, cte.grp
from cte
inner join #temp2 t2
on t2.Pre_ID=cte.id
)
select * from cte
order by id;

How to prevent CTE execution until reached OR NOT EXISTS

I have an SQL Server query that uses some CTEs (Common Table Expressions). It has two tables that it selects the data from. The two tables are identical in structure, but not necessary data. The query will first select from table_a and if no rows are fetched, it then selects from table_b. The query is something like this:
;WITH cte_a AS (
...
), cte_b AS (
...
)
SELECT *
FROM table_a
INNER JOIN cte_a ON condition_a
OR NOT EXISTS (
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b
)
The current problem that I have is that cte_b will always be executed regardless of whether table_a returns any rows. This is not very ideal for me; I would like to have cte_b execute if and only if the subquery for table_a returns no rows.
I tried moving the cte_b to be just before the subquery for table_b as
;WITH cte_a AS (
...
)
SELECT *
FROM table_a
INNER JOIN cte_a ON condition_a
OR NOT EXISTS (
;WITH cte_b AS (
...
)
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b
)
However, the IDE complains. I think that this wasn't the way CTEs are supposed to be used.
Create temporary table for storing the data - split the query to two separate INSERT statements, where the second is executed only in no data is populated after first query is completed. Something like this:
CREATE TABLE #TEmp
(
);
;WITH cte_a AS (
...
)
INSERT INTO #TEmp
SELECT *
FROM table_a
INNER JOIN cte_a ON condition_a
IF NOT EXISTS(SELECT 1 FROM #TEmp)
BEGIN;
INSERT INTO #TEmp
SELECT *
FROM table_a
WHERE NOT EXISTS (
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b
)
This is the nature of CTE's.
The best thing would be to not use a CTE and use a join, but I assume you can't.
I'd suggest you try using a sub-query so the engine can process it all at once.
I would phrase this using a union, and then excluding the second half of the union on cte_b should the first CTE have any results.
;WITH cte_a AS (
...
),
cte_b AS (
...
)
SELECT *
FROM table_a
INNER JOIN cte_a ON condition_a
UNION ALL
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b
WHERE NOT EXISTS (
SELECT 1
FROM table_a
INNER JOIN cte_a ON condition_a
)
;WITH cte1 AS
(
....
),
cte2 AS
(
...
)
SELECT *
FROM table_a
INNER JOIN cte_a ON condition_a ---Choose Your Condition...
UNION ALL
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b ---Choose Your Condtion....
WHERE NOT EXISTS (SELECT * FROM cte2)
Note:-
A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE statement that references some or all the CTE columns.

Possible to reference previous query in new select query?

If i just created a select query and want to use the new data in a new query do I reference the previously created query as the FROM in a new select query? The query I just created in my database is listed as SQLQuery1.sql so is that what I put as the FROM for the new query?
Here is an example of a query that contains multiple select statements:
SELECT T1.col_a, T1.col_b, T2.col_c
FROM (SELECT col_a, col_b, ...etc...) AS T1
JOIN (SELECT col_a, col_c, ...etc...) AS T2
ON T1.col_a = T2.col_a
I would use CTE (Common Table Expression).
Have a look at the following code:
WITH MainQuery
AS
(
select col1, col2, col3
from dbo.TableName
)
select a.col1, a.col2, a.col3, b.col1
from MainQuery as a
join someotherdata as b
on a.col1 = b.col1;

Sql server DELETE and WITH clause

I need to build an SQL statement to delete from certain table the records that match another select statement.
In Teradata we use
delete from table1
where (col1, col2) in (
select col1,col2
from table2
)
While in SQL Server it's not allowed to have more than 1 column in the WHERE..IN clause. I thought I can use the WITH clause:
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete from table1
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
How to use WITH..DELETE clause? Is there another way?
This should do it:
DELETE Table1
from Table1 t1
inner join tempTable t2
on t2.Col1 = t1.Col1
and t2.Col2 = t1.Col2
First build a query that selects the rows you need:
SELECT t1.*
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col2]=t2.[Col2]
Test it to make sure it returns exactly the rows you want to delete. Then turn it into a delete statement by changing the "SELECT" to "DELETE" and removing the column list:
DELETE t1
FROM [Table1] t1
INNER JOIN [Table2] t2 ON t1.[col1] = t2.[col1] AND t1.[Col
delete from table1 t1 where exists
(
select 1 from table2 t2 where t1.col1 = t2.col1 and t1.col2 > t2.col2
)
with tempTable(col1,col2) as (
select col1,col2
from table2
)
delete table1 from tempTable
where table1.col1 = tempTable.col1
and table1.col2 = tempTable.col2
This works for me
WITH CTE AS
(
SELECT TOP 50000 *
from v020101hist order by data
)
DELETE FROM CTE

Resources