Does Teradata support -Multiple With Clause? - sql

Trying to execute in SQLAssitant (v 15.x Teradata):
WITH TEMP1 (EMP_ID,E_NAME,E_SAL) AS (WITH TEMP (EMP_ID,E_NAME,E_SAL) AS (SELECT EMP_ID,E_NAME,E_SAL FROM EMP_TABLE_TEST)
SELECT EMP_ID,E_NAME,E_SAL FROM TEMP) SELECT EMP_ID,E_NAME,E_SAL FROM TEMP1
Error: SELECT Failed. 6926: definitions, views, triggers or stored procedure
WITH TEMP (EMP_ID,E_NAME,E_SAL) AS (SELECT EMP_ID,E_NAME,E_SAL FROM EMP_TABLE_TEST ) , TEMP1 (EMP_ID,E_NAME,E_SAL) AS (
SELECT EMP_ID,E_NAME,E_SAL FROM TEMP) SELECT EMP_ID,E_NAME,E_SAL FROM TEMP1
Error: SELECT Failed. 3807: Object 'TEMP' does not exist.
Does Teradata really support Multiple WITH clause or WITH within WITH clause?
I heard it is supported in 14.x higher version but it is not supporting for 15.x.

The syntax is different (and is the same as in other databases)
With t1 as (...),t2 as (...), t3 as (...) select ...
Currently the reference order is upside-down -
t2 can refer t3 and t1 can refer t2 and t3.
The "right" order will be supported in TD16.

This has been fixed in Teradata 16. Please see the release summary chapter 2.
http://www.info.teradata.com/doclist.cfm?RetainParams=Y&FilterCall=Y&selDocType=100
Previously, when a nonrecursive WITH clause defined multiple CTEs, a CTE could only reference a
subsequent CTE in the WITH clause. Now, a CTE can reference a preceding or subsequent CTE in the
WITH clause.
From Teradata Release Summary for version 16

Related

Generating a stable uuid ID across with clauses in GBQ [duplicate]

This question already has an answer here:
BigQuery GENERATE_UUID() and CTE's
(1 answer)
Closed 1 year ago.
I'm trying to generate a UUID within a with clause on GBQ and then use it in a subsequent with clause for a join.
with q1 as (
select generate_uuid() as uuid
), q2 as (
select uuid from q1
)
select * from q1
union all
select * from q2
This returns two distinct uuid.
How would I go about generating an ID that stays the same across with clauses?
I'll start with the reason behind this discrepancy.
TLDR; as of today there is no option to force BigQuery to materialize CTE results. It'd be useful when a CTE referenced more than once in a statement.
see below query:
with cte_1 as (
select count(1) as row_count
from `bigquery-public-data.austin_311.311_service_requests` as sr
)
, cte_2 as (
select row_count
from cte_1
)
select row_count
from cte_1
union all
select row_count
from cte_2;
when the execution plan is examined, you'll see 2 Input stage for referenced sr table.
It'd be great if we have an option to materialize CTE results. As I remember, oracle has this implicitly if CTE used more than once or explicitly via hints.
materializing q1 explicitly to table then use it twice might be a workaround. I'd prefer temporary table.
the drawback is; the cost may increase if your project uses on-demand pricing. (rather than flat-rate)
Because subquery always executes each time it is called, so with your query, the generate_uuid will be called twice for both q1 and q2 tables.
I suggest you save the generated UUID to a table, then query from this to make sure the UUID is the same from both tables.

Cannot use a CTE in a scalar subquery in Db2

I'm trying to use a CTE in a DB2 LUW v11.5.4.0 scalar subquery, but this doesn't work:
SELECT 1
FROM SYSIBM.dual
WHERE 1 IN (
WITH t (x) AS (SELECT 1 FROM SYSIBM.dual)
SELECT * FROM t
);
I'm getting this error:
SQL Error [42601]: An unexpected token "AS" was found following "1 IN (
WITH t (x)". Expected tokens may include: "JOIN".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.26.14
Can this be done? Is there a workaround?
(This is similar but not the same as this question, which is about derived tables, not scalar subqueries. Derived tables support CTE in version 11.5.4.0)
It seems that in version 11.5.4.0, it's possible to use CTEs in derived tables, so the query can be emulated as follows:
SELECT 1
FROM SYSIBM.dual
WHERE 1 IN (
SELECT *
FROM (
WITH t (x) AS (SELECT 1 FROM SYSIBM.dual)
SELECT * FROM t
) t
);
However, this workaround also doesn't work in older versions of Db2, e.g. in version v11.1.4.4 as can be seen in this dbfiddle or in this question. The workaround in those versions will be to push the CTE to the top level of the query:
WITH t (x) AS (SELECT 1 FROM SYSIBM.dual)
SELECT 1
FROM SYSIBM.dual
WHERE 1 IN (
SELECT * FROM t
);
Side note
HSQLDB seems to suffer from a similar limitation / bug, see https://sourceforge.net/p/hsqldb/bugs/1617.

Is there a way to elemenate a subquery from this Hive query?

Edit: I am using Apache Hive (version 3.1.0.3.1.5.0-152)
When I run the following query:
insert into delta_table (select * from batch_table where loaddate=(select max(loaddate) from batch_table));
I get this error:
Unsupported SubQuery Expression 'loaddate': Only SubQuery expressions
that are top level conjuncts are allowed
We have a table that is written to in daily batches with the column loaddate that is unique for each batch. The purpose of the query is to get all the records from the most recent batch without knowing what it's load date is.
I suspect the issue is because I am using a subquery inside a subquery. Is there a way to change this query to do the same thing, but without the last subquery?
Depends on which version of hive you have , but you can use the Clause with to avoid the second subquery
with max_load as ( select max(loaddate) as loaddate from batch_table)
insert into delta_table
(select * from batch_table a where a.loaddate=max_load.loaddate);
It looks like the error was because the table was created incorrectly and for some reason this caused the query to fail. I recreated the table and it now works
Analytic function + filter will be more efficient than self-join or subquery with one more table scan to find max date:
insert into delta_table
select col1, col2, ... coln --list columns here
from
(
select t.*, rank() over(order by loaddate desc) rnk
from batch_table t
)s
where rnk=1;

Hive: less than operator error in subquery

I want the latest records from HIVE table using the following query-
WITH lot as (select *
from to_burn_in as a where a.rel_lot='${Rel_Lot}')
select a.* from lot AS a
where not exists (select 1 from lot as b
where a.Rel_Lot=b.Rel_Lot and a.SerialNum=b.SerialNum and a.Test_Stage=b.Test_Stage
and cast(a.test_datetime as TIMESTAMP) < cast(b.Test_Datetime as TIMESTAMP))
order by a.SerialNum
this query is throwing a error as
Error while compiling statement: FAILED: SemanticException line 0:undefined:-1 Unsupported SubQuery Expression 'Test_Datetime': SubQuery expression refers to both Parent and SubQuery expressions and is not a valid join condition.
I have tried running with equal operator in place of the less than operator in subquery and it is running fine. I read the HIVE documentation as given in
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries
and couldn't figure out why it is throwing a error as 'where' subquery is supported.
What might be the problem here?
EXISTS works the same as a join actually. Not equality join conditions are not supported in Hive prior Hive 2.2.0 (see HIVE-15211, HIVE-15251)
It seems you are trying to get records having latest timestamp per Rel_Lot,SerialNum,Test_Stage. Your query can be rewritten using dense_rank() or rank() function:
WITH lot as (select *
from to_burn_in as a where a.rel_lot='${Rel_Lot}'
)
select * from
(
select a.*,
dense_rank() over(partition by Rel_Lot,SerialNum,Test_Stage order by cast(a.test_datetime as TIMESTAMP) desc) as rnk
from lot AS a
)s
where rnk=1
order by s.SerialNum

Oracle VPD how to reference the table

I'm struggling with the following problem. I want to restrict access to a table using Oracle VPD. In the where clause that the select policy function returns I need a reference to the table in a subquery as follows:
select * from Table t1
where not exists (select 1 from Table t2 where t2.name=t1.name and t2.date=t1.date)
(The example doesn't make a lot of sense except to illustrate the problem)
I have no control over the select part of the query.
select * from Table t1
The table can be given any alias or none at all. So therefore I have no idea how to reference the table in the where clause.
Is there a way to get around this?
(Oracle 10GR2)
I think you will need to use NOT IN:
(name, datecol) not in (select name, datecol from table2)