I've found an interesting recursive query here (http://beyondrelational.com/modules/2/blogs/28/posts/10486/recursive-cte-and-ordering-of-the-hierarchical-result.aspx) and I adapted to my needs, but is not working.
Here's the code:
WITH cte AS (
SELECT 0 AS lvl, collectionID, collectionName, parentCollectionID, CAST(collectionID AS VARCHAR(128)) AS Sort
FROM collections WHERE parentCollectionID IS NULL
UNION ALL
SELECT p.lvl + 1, c.collectionID, c.collectionName, c.parentCollectionID, CAST(p.Sort + '/' + CAST(c.collectionID AS VARCHAR) AS VARCHAR(128))
FROM collections c
INNER JOIN cte p ON p.collectionID = c.parentCollectionID
)
SELECT
collectionID,
SPACE(lvl * 4) + collectionName AS collectionName,
Sort,
parentCollectionID
FROM cte ORDER BY Sort;
I receive this message: "Kernel error: near "WITH": syntax error"
Please, what I have to do to fix it?
I'm using SQLIte 3.8.2
Related
Technology: Teradata 16.20
I'm trying to update a table, that takes data from another table which uses CTE data.
I'm getting below error:
Error:
select failed 3707 syntax error, expected something like a 'SELECT' keyword or '(' or a 'TRANSACTIONTIME' keyword or a 'VALIDTIME' keyword between ')' and the 'UPDATE' keyword
Question:
Is it possible to update a table using another table that is getting joined with cte?
I know it can be done with a volatile table. I have seen CTE with insert statement and with select statement, but never seen cte with an update statement. Writing the same sql over and over for multiple self join only increases the lines of code. If this update can be done using CTE, that would be much easier and understandable
Code:
WITH NAME_CTE AS (
SELECT FIRST.ID,FIRST.NAM,LAST.NAME
FROM TABLE_FIRST FIRST INNER JOIN TABLE_LAST LAST
ON FIRST.ID = LAST.ID
)
UPDATE SUBJECT_TEACHER_TABLE
FROM (
SELECT CROSS_TBL.SUB_ID,
COALESCE(CTE1.NAM,CTE1.NAME,CTE2.NAM,CTE2.NAME) AS FINAL_NAME
FROM CROSS_REFERENCE_TABLE CROSS_TBL
LEFT JOIN NAME_CTE CTE1 ON CROSS_TBL.CR_ID1 = CTE.ID
LEFT JOIN NAME_CTE CTE2 ON CROSS_TBL.CR_ID2 = CTE.ID
) PV
SET
FINAL_NAME = PV.FINAL_NAME
WHERE SUBJECT_TEACHER_TABLE.SUB_ID = PV.SUB_ID;
Modified Query: As per #dnoeth suggesstion
UPDATE SUBJECT_TEACHER_TABLE
FROM (
WITH NAME_CTE AS (
SELECT FIRST.ID,FIRST.NAM,LAST.NAME
FROM TABLE_FIRST FIRST INNER JOIN TABLE_LAST LAST
ON FIRST.ID = LAST.ID)
SELECT CROSS_TBL.SUB_ID,
COALESCE(CTE1.NAM,CTE1.NAME,CTE2.NAM,CTE2.NAME) AS FINAL_NAME
FROM CROSS_REFERENCE_TABLE CROSS_TBL
LEFT JOIN NAME_CTE CTE1 ON CROSS_TBL.CR_ID1 = CTE.ID
LEFT JOIN NAME_CTE CTE2 ON CROSS_TBL.CR_ID2 = CTE.ID
) PV
SET
FINAL_NAME = PV.FINAL_NAME
WHERE SUBJECT_TEACHER_TABLE.SUB_ID = PV.SUB_ID;
Error:
SQL Error [3807] [42S02]: [Teradata Database] [TeraJDBC 15.10.00.22] [Error 3807] [SQLState 42S02] Object 'NAME_CTE' does not exist.
I need to create a teradata macro to extract information into a volatile table first, then do CTE to extract data from this volatile table and insert into a teradata table, tried different ways all fail, appreciate help!
CREATE MACRO database.macro_insertion_tablename AS (
CREATE VOLATILE TABLE vt AS
(
SELECT
id, bu,
CONCAT(TO_CHAR(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action) AS full_action,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) AS row_num,
COUNT(*) OVER (PARTITION BY id) as cnt
FROM database.table1
) WITH DATA UNIQUE PRIMARY INDEX(id, row_num) ON COMMIT PRESERVE ROWS;
WITH RECURSIVE cte (id, bu, act, rn) AS
(
SELECT
id, bu
,CAST(full_action AS VARCHAR(5000)) AS full_action
,row_num
FROM vt
WHERE row_num = cnt
UNION ALL
SELECT
vt.id, vt.bu
,cte.act || ' / ' || vt.full_action
,vt.row_num
FROM vt
JOIN cte On vt.id = cte.id AND vt.row_num = cte.rn - 1
)
INSERT INTO database.table (id, bu, full_action)
SELECT id, bu, act
FROM cte
WHERE rn = 1;
DROP TABLE vt;
);
DDL must be the only statement in a Teradata Macro.
As workaround you could switch to a Global Temporary Table which is defined once and then you simply Insert/Select into it instead of CREATE VOLATILE TABLE.
But in your case there's no need for a temp table plus inefficient recursive processing to get a "group concat":
SELECT id, max(bu) -- maybe min(bu)?
XmlAgg(Concat(To_Char(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action)
ORDER BY comment_date) (VARCHAR(5000)) AS full_action
FROM database.table1
GROUP BY 1
will give you a similar result.
To follow up on my comments, you should be able to define multiple CTEs in the same statement. It may be tricky getting the RECURSIVE CTE to work, but it sounds like it's possible. Maybe something like this:
CREATE MACRO database.macro_insertion_tablename AS (
WITH vt (id, bu, full_action, row_num, cnt) AS
(
SELECT
id, bu,
CONCAT(TO_CHAR(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action) AS full_action,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) AS row_num,
COUNT(*) OVER (PARTITION BY id) as cnt
FROM database.table1
),
RECURSIVE cte (id, bu, act, rn) AS
(
SELECT
id, bu
,CAST(full_action AS VARCHAR(5000)) AS full_action
,row_num
FROM vt
WHERE row_num = cnt
UNION ALL
SELECT
vt.id, vt.bu
,cte.act || ' / ' || vt.full_action
,vt.row_num
FROM vt
JOIN cte On vt.id = cte.id AND vt.row_num = cte.rn - 1
)
INSERT INTO database.table (id, bu, full_action)
SELECT id, bu, act
FROM cte
WHERE rn = 1;
);
I don't have a Teradata system to test with, so not 100% it will work as-is, but give it a try. You may need to change RECURSIVE to WITH RECURSIVE and also the ordering of the CTE queries (i.e. put the RECURSIVE one first). Take a look at these two links:
Teradata Forum - Multiple With Clause
teradata Forum - Common Table Expressions
I am trying to delete all rows in a simple table that have a duplicate value except for the duplicate with the highest id.
Table:
CREATE TABLE IF NOT EXISTS [Expression] (
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Value] VARCHAR(2048) NOT NULL
)
Attempted Queries:
DELETE Expression
WHERE EXISTS (
SELECT 1
FROM Expression Exp2
WHERE Expression.Value=Exp2.Value
AND Expression.Id < Exp2.Id)
fails with
"SQL logic error or missing database near "Expression":syntax error"
DELETE Exp1
FROM Expression Exp1
INNER JOIN Expression Exp2
ON Exp1.Value=Exp2.Value AND Exp1.Id < Exp2.Id
fails with
"SQL logic error or missing database near "Exp1":syntax error"
What syntax do I need to use?
Don't forget the FROM.
DELETE command
DELETE FROM Expression
WHERE EXISTS (
SELECT 1
FROM Expression Exp2
WHERE Expression.Value=Exp2.Value
AND Expression.Id < Exp2.Id
);
You can do this with many ways:
1) USING CTE:
WITH CTE AS (
SELECT ID, VALUE, ROW_NUMBER() OVER(ORDER BY Value) as RowNum
FROM Expression
)
DELETE
FROM CTE
WHERE ROWNum >1
2) USING Temp tables: Same concept
DELETE t1 FROM contacts t1 INNER JOIN contacts t2 WHERE t1.id < t2.id AND t1.email = t2.email;
This is the query that I am using. I am getting an error with this query. 'syntax error near 'WITH' clause.
WITH RECURSIVE under_cust (affiliation_id, from_customer_id, to_customer_id, to_name, parent_customer_type, child_customer_type, level)
AS (SELECT af.affiliation_id,
from_customer_id,
to_customer_id,
to_name,
parent_customer_type,
child_customer_type,
0 LEVEL
FROM affiliation af,
customer c
WHERE to_customer_id <> from_customer_id
AND af.from_customer_id = c.customer_id
AND af.to_customer_id = 1000022559337
UNION ALL
SELECT af.affiliation_id,
af.from_customer_id,
af.to_customer_id,
af.to_name,
af.parent_customer_type,
af.child_customer_type,
under_cust.level + 1 LEVEL
FROM customer c,
affiliation af
JOIN under_cust smr
ON smr.from_customer_id = af.to_customer_id
WHERE af.from_customer_id = c.customer_id
) SELECT affiliation_id,
to_customer_id parent,
from_customer_id child,
to_name,
parent_customer_type,
child_customer_type,
level
FROM under_cust
Common table expressions and the WITH syntax were introduced only recently in sqlite version 3.8.3.
If you run the query on an older version, you get the syntax error.
Either upgrade your sqlite or make your code work without the WITH syntax.
I keep getting this error in SQLite:
Query Error: near "FROM": syntax error Unable to execute statement
SELECT Name, CourseId
FROM Lecturer JOIN Lecture ON Lecturer.LecturerId = Lecture.LecturerId
JOIN (SELECT CourseId
FROM Course
WHERE EXISTS (SELECT *
FROM Exam
WHERE Exam.CourseId = Course.CourseId
AND (SELECT COUNT *
FROM Exam
WHERE Grade > 6)
<
(SELECT COUNT *
FROM Exam
WHERE Grade < 6)))
USING Course.Id
I would normally assign the inline view an alias, e.g FOO, and join an outer table to the inline view with an on... clause:
select * from x
join
(
select someColumn, someOtherColumn...
) as FOO
on x.somecolumn = FOO.somecolumn
I would go about it this way:
select lecture.*, FOO.courseid
from lecture
join lecturer on lecture.lecturerid = lecturer.lecturerid
join
(
you inline view selecting the courses
) as FOO
on lecture.courseid = FOO.courseid
COUNT is a function, you need parens around the *
Such as:
COUNT(*)