sql with clause within a with clause - sql

can i do something like this :
with t as
(
with tt as
(
select * from table
)
SELECT * FROM tt
)
select * from t
i willing to perform some logic on output of inner with clause & than again do some operations on output of the outer with clause.
any help will be appreciated ...
Thanks
note :- its just some simplified query that will resolve my problem in my actual query, which have nested with clause

You can do something like this:
with t as
(
select * from table
),
tt as
(
select * from t
)
select * from tt

No, you cannot nest CTE (Common Table Expression) but you can chain them:
with t as
(
select * from table
),
tt as
(
select * from t
)
SELECT * FROM tt

Related

How to delete the duplicates from the table using row_number() in psql?

I have written the following query, i am using greenplum db and dbeaver for implementation.
with cte as
(select
*,
row_number() over(partition by first_name order by roll_num) row_num
from table_name
where roll_num in ('0011'))
delete from cte where row_num>1;
The above query is returning error. Can someone help me here, please!
How about this:
PostgreSQL DELETE statement with USING clause
Ref: PostgreSQL Docs
Please try like this it works for me:
select * from tablename as t
where exists
( select *
from tablename as d
where d.ctid > t.ctid
and d.* is not distinct from t.*
) ;
delete from tablename as t
where exists
( select *
from tablename as d
where d.ctid > t.ctid
and d.* is not distinct from t.*
) ;

Presto create table with 'with' queries

typically to create a table in Presto (from existing db tables), I do:
create table abc as (
select...
)
But to make my code simple, I've broken out subqueries like this:
with sub1 as (
select...
),
sub2 as (
select...
),
sub3 as (
select...
)
select
from sub1 join sub2 on ...
join sub3 on ...
Where do I put the create table statement here? The actual query is more complex than the above so I am trying to avoid having to put the subqueries within the main query.
This is possible with an INSERT INTO not sure about CREATE TABLE:
INSERT INTO s1
WITH q1 AS (...)
SELECT * FROM q1
Maybe you could give this a shot:
CREATE TABLE s1 as
WITH q1 AS (...)
SELECT * FROM q1
If Strings are concerned, then following works
WITH sample AS (
SELECT * FROM (VALUES ('strA', 'strB'), ('strC', 'strD'), ('strE', 'strF')) AS account (name, cat)
)
SELECT name, cat from sample;
if integers are only concerned values , then following works: -
WITH slab (SNo,Amount) AS (VALUES (1,1000),(2,2000),(3,3000),(4,4000),(5,5000),(6,6000),(7,7000),(8,8000),(9,9000),(10,10000),(11, 11000),(12,12000),(13,13000),(14,14000),(15,15000),(16,16000),(17,17000),(18,18000),(19,19000),(20,20000),(21,21000),(22,22000),(23,23000),(24,24000),(25,25000),(26,26000),(27,27000),(28,28000),(29,29000),(30,30000),(31,31000),(32,32000),(33,33000),(34,34000),(35,35000),(36,36000),(37,37000),(38,38000),(39,39000),(40,40000),(41,41000),(42,42000),(43,43000),(44,44000),(45,45000),(46,46000),(47,47000),(48,48000),(49,49000),(50,50000),(51,51000)
)
SELECT * FROM slab;
Syntax is just as if you prepend create table .. as to the select. E.g. the following worked for me on Presto 0.170:
create table memory.default.a as
with w as (
select * from (values 1) t(x)
)
select * from w;
(I use experimental memory connector so that this is copy-pastable to try it out.)
I believe you need to 'wrap' the entire query like this:
create table EXAMPLE as (
with sub1 as (
select ...
),
.......
select
from sub1....
)
This works
create table answertable as
(
select * from (
WITH
q as ( select findcode from (values 'G463','G464','G465','G466','G467','G468','I64','I694') as concept(findcode) )
select s.*
from table1 s
inner join q on starts_with(s.xxx, q.findcode)
where s.pk is not null
)
)

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;

SQL if statement within WHERE clause

I want to do the following query, how can I implement it?
SELECT * FROM table WHERE routeNum LIKE 'N10%'
-->if no rows return, WHERE clause change to routeName LIKE '&something%'
I think this will work for you:
WITH CTE AS (
SELECT 2 AS 'INDEX', * FROM table WHERE routeNum LIKE 'N10%'
UNION ALL
SELECT 1 AS 'INDEX', * FROM table WHERE routeNum LIKE '&something%'
)
SELECT *
FROM CTE
WHERE CTE.INDEX = (SELECT MAX(INDEX) FROM CTE)
As you have to choose between two result sets, you will need two queries, which will return two different sets and then, based on the 'index' which corresponds to the query that has run, you choose how to display your results.
Here is a SQLFiddle demo.
A possible solution
WITH cte AS
(
SELECT *
FROM routes
WHERE routeNum LIKE 'N10%'
)
SELECT * FROM cte
UNION ALL
SELECT * FROM routes
WHERE routeNum LIKE 'something else%'
AND NOT EXISTS
(
SELECT *
FROM cte
)
Here is SQLFiddle demo
WITH tmp AS
(
SELECT t.*,
CASE
WHEN routeNum LIKE 'N10%' THEN 1
WHEN routeNum LIKE '&something%' THEN 2
ELSE 3 END AS q
FROM table t
)
SELECT * FROM tmp t
WHERE q = CASE WHEN (SELECT COUNT(*) FROM tmp WHERE q = 1 ) > 0 THEN 1 ELSE 2 END

Count rows in more than one table with tSQL

I need to count rows in more than one table in SQL Server 2008. I do this:
select count(*) from (select * from tbl1 union all select * from tbl2)
But it gives me an error of incorrect syntax near ). Why?
PS. The actual number of tables can be more than 2.
In case you have different number of columns in your tables try this way
SELECT count(*)
FROM (
SELECT NULL as columnName
FROM tbl1
UNION ALL
SELECT NULL
FROM tbl2
) T
try this:
You have to give a name to your derived table
select count(*) from
(select * from tbl1 union all select * from tbl2)a
I think you have to alias the SELECT in the FROM clause:
select count(*)
from
(
select * from tbl1
union all
select * from tbl2
) AS SUB
You also need to ensure that the * in both tables tbl1 and tbl2 return exactly the same number of columns and they have to be matched in their type.
I don't like doing the union before doing the count. It gives the SQL optimizer an opportunithy to choose to do more work.
AlexK's (deleted) solution is fine. You could also do:
select (select count(*) from tbl1) + (select count(*) from tbl2) as cnt