Error on using union clause in cte sql query - sql

I'm trying to do following but getting an max recursive error. Can someone please help?
Sample code to demonstrate what I'm trying to achieve:
DECLARE #SecurityMaster AS TABLE
(
ID INT,
SecurityAlias INT,
LegNumber INT
)
INSERT INTO #SecurityMaster
SELECT 12829, 3030106, NULL
UNION ALL
SELECT 12829, 3030107, 1
SELECT * FROM #SecurityMaster;
WITH CTE1 (ID, SecurityAlias, LegNumber)
AS
(
SELECT S.ID, S.SecurityAlias, S.LegNumber
FROM #SecurityMaster S
WHERE S.LegNumber IS NOT NULL
UNION ALL
select s.ID, s.SecurityAlias, s.LegNumber
from #SecurityMaster S inner join CTE1 c on s.ID = c.ID
where s.LegNumber is NULL
)
SELECT *
FROM CTE1;
Result I'm expecting:
ID SecurityAlias LegNumber
-----------------------------------------
12829 3030107 1
12829 3030106 NULL

Your questionis difficult to understand, but will this work for you?
select s.ID, s.SecurityAlias, s.LegNumber
from #SecurityMaster S
where s.LegNumber is NULL
And s.id in (SELECT f.ID
FROM #SecurityMaster f
WHERE f.LegNumber IS NOT NULL)

Related

Postgres - query taking long time

I have a query which is taking a long time. Is there anyway to write it better and in optimized way:
select 1, my_text from (
select distinct a.my_text||'_'||b.my_text my_text from (
select r_id, my_text
from tmp_v
where r_id in (
select o_id
from tmp_recid
) and v_id in (
select v_id
from o_v
where v_id in (
select o_id from tmp_record_vaid
union
select o_id from tmp_vue_vaid
) and va_nm = 'My V'
)
) a,
(
select r_id, my_text
from tmp_v
where r_id in (
select o_id
from tmp_recid
) and v_id in (
select v_id
from o_v
where v_id in (
select o_id from tmp_record_vaid
union
select o_id from tmp_vue_vaid
) and va_nm = 'My V 2'
)
) b
where a.r_id = b.r_id
except
select e_nm
from myp_ent_id
where p_m_id = 1 and entity_id in (
select entity_id
from o_e_t
where p_m_id = 1 and tag = 'Ample' and tag_category = 'My Type'
)
) a;
please, try with below query except "except query":
select 1, distinct(CONCAT(TV1.my_text, '_'))
from tmp_v TV1
left outer join tmp_recid TR1 on TR1.o_id = TV1.r_id
left outer join o_v OV1 on OV1.v_id = TV1.v_id and OV1.va_nm in ('My V', 'My V 2')
left outer join tmp_record_vaid TRV1 on OV1.v_id = TRV1.o_id
left outer join tmp_vue_vaid TVV1 on OV1.v_id = TVV1.o_id
where TR1.o_id is not null and (TRV1.o_id is not null OR TVV1.o_id is not null)
group by TV1.r_id
First level optimization: I combined two sub queries a and b(tmp_v) into one using CASE as the conditions are common for both.
select 1,my_text(
select distinct string_agg(amytext,'')||'_'||string_agg(bmytext,'') as mytext(
select r_id,case va_nm='My V' then my_text else null end as amy_text,case va_nm='My V 2' then my_text else null end as bmy_text
from tmp_v
where r_id in
(select o_id from tmp_recid)
and v_id in (select v_id from o_v where v_id in (select o_id from tmp_record_vaid union select o_id from tmp_vue_vaid))
)
except
select e_nm
from myp_ent_id
where p_m_id = 1 and entity_id in (
select entity_id
from o_e_t
where p_m_id = 1 and tag = 'Ample' and tag_category = 'My Type'
)
)a;
Further you can replace IN with EXISTS.

How to add a temp table in SQL server

I am trying to add a temp table to my query so that I can query that temp table, I have searched the internet but I couldn't get a solution.
this is my query
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
which gives me the following when I run it
ID | Name
1111 | BaseBall
2222 |BasketBall
45896 |Relay
now I tried to create a temp table as follows
Create Table #temp(
ID int,
Name varchar
)
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK)
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
insert into #temp // i wanted to set these values in the temp table
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
every time I try to store this information in the temp table it gives me an error 'Column name or number of supplied values does not match table definition.' But I only have two values in. What am I doing wrong that I cant see?
First, why not just use select into?
IF OBJECT_ID('TempDB..#temp') IS NOT NULL
BEGIN
DROP TABLE #temp
END
select c.ID, c.Name
into #temp
from . . .
Then you don't need to define #temp as a table.
Next, your definition is bad, because Name has only one character. This would be fixed with select into.
However, I don't know why you are getting the particular error you are getting. The numbers of columns appears to match.

Transposing Rows to Columns and having values flow down in TSQL

I am using TSQL.
If I have the following results:
And I want to transpose this to be like this:
How can I achieve this?
I have the following query:
WITH q AS (
SELECT *
FROM tableOne
WHERE ID = 1
UNION ALL
SELECT m.*
FROM tableOne m
JOIN ON m.ParentID = q.ID
)
SELECT *
FROM q
This gives me all of the items underneath the specified node including the specified node.
It could be easy for us to help you if you add scripting data and not an image. Note that tbl is the name of your table, it is called 3 times. Try this:
select
a.fieldValue company,
b.fieldValue department,
c.fieldValue Job
from tbl a
inner join tbl b on a.parentId is null and a.id=b.parentID
inner join tbl c on b.id= c.parentID
If it does not bring desired results please add data as text and let me know, I could modify the query
Another option (assuming this is NOT a jagged hierarchy).
This is a standard Recursive CTE, with a little twist in the final SELECT
Example
;with cteP as (
Select ID
,ParentID
,PathID = cast(FieldValue as varchar(max))
From YourTable
Where ParentID is Null
Union All
Select ID = r.ID
,ParentID = r.ParentID
,PathID = cast(p.PathID+'|||'+r.FieldValue as varchar(max))
From YourTable r
Join cteP p on r.ParentID = p.ID)
Select ID
,B.*
From cteP A
Cross Apply (
Select Company = xDim.value('/x[1]','varchar(max)')
,Department = xDim.value('/x[2]','varchar(max)')
,Job = xDim.value('/x[3]','varchar(max)')
From (Select Cast('<x>' + replace(PathID,'|||','</x><x>')+'</x>' as xml) as xDim) as X
) B
Where ID not in (Select Distinct ParentID from YourTable where ParentID is not null)
Order By PathID
Returns

Unable to JOIN and get the final query

I'm having this following situation for which i'm unable to form a sql query. Please help me with this.
create table student(
studentName varchar(50)
);
Insert into student values('abc');
Insert into student values('mnop');
Insert into student values('xyz');
Insert into student values('pqrs');
create table workAssigned (
topic varchar(50),
creator varchar(50),
reviewer varchar(50),
creationCount decimal(4,2)
reviewCount decimal(4,2)
);
insert into workAssigned values('algebra','abc','mnop',1.25,0.75);
insert into workAssigned values('geometry','mnop','xyz',1.5,0.25);
insert into workAssigned values('algorithms','mnop','xyz',1.5,1.5);
insert into workAssigned values('derivative','xyz','abc',0.25,1);
final output reqiured is:
StudentName NumberOfWorkDone Effort
abc 2 2.25
mnop 3 3.75
xyz 3 2
pqrs NUll NULL
Where NumberOfWorkDone is SUM of creator and Reviewer, and
Effort is SUM of creationCount and reviewCount
You can try using Group By, Join and CASE with Aggregate functions,
SELECT studentName,
SUM(CASE WHEN W.creator = S.studentName OR S.studentName = W.reviewer THEN 1 ELSE NULL END ) AS NumberOfWorkDone,
SUM(CASE WHEN W.creator = S.studentName THEN W.creationCount WHEN S.studentName = W.reviewer THEN W.REVIEWCOUNT ELSE NULL END) AS Efforts
FROM student S
LEFT JOIN workAssigned W
ON S.studentName = W.creator OR S.studentName = W.reviewer
GROUP BY studentName
I have added NULL into Case statement for else part as your output was showing NULL but I think it would be better if you would replace that with 0.
Select studentName,NumberOfWorkDone,Effort
From student as A
Left Join
(
Select creator,count(creator) as NumberOfWorkDone,sum(creationCount) as Effort
From
(
Select creator,creationCount
from workAssigned as A
Union all
Select reviewer,reviewCount from workAssigned
)as A
Group by creator
)as B
On A.studentName=B.creator
select * from
(select count(col_X) as F, col_X
from
(select creator as col_X from workAssigned
UNION ALL
select reviewer as col_X from workAssigned) AS A
group by col_X) as E
left join
(select A, sum(B)
from
(select creator as A, creationCount as B
from workAssigned
UNION ALL
select revieweras A, reviewCount as B
from workAssigned) as C
group by A) as D
on E.F = D.A

Reference a view inside of the view in postgresql

I would like to do something like the following:
CREATE VIEW foo_view AS
SELECT
foo.id,
foo.carryover_id,
foo.amount,
(SELECT SUM(foo_view.total)
FROM foo_view
WHERE foo_view.carryover_id = foo.id
) AS carryover_amount,
(amount + carryover_amount) AS total;
However, this raises an error relation "foo_view" does not exist. I would think that RECURSIVE would come in handy here, but the documentation is more reference than tutorial and there don't seem to be any resources out there to help me. Thoughts?
EDIT
Here's a sqlfiddle with a relevant schema http://sqlfiddle.com/#!15/6834d/1
You are right, your article is what you needed.
I formatted the data first into a fooBar temp table:
SELECT b.id
, foo_id
, ISNULL(f.carryover_id, foo_id) as carryover_id
, b.amount
, ROW_NUMBER() OVER(
PARTITION BY ISNULL(f.carryover_id, foo_id)
ORDER BY b.id asc) as rowNmbr
INTO #fooBar
FROM #bar as b
INNER JOIN #foo as f
ON b.foo_id = f.id;
The first row in the WITH is the top level. Then it recursively goes through each level. The rowNmbr is the level.
WITH summarizedFoo(rowNmbr, id, foo_id, carryover_id, amount, totalAmount)
AS
(
SELECT f.rowNmbr
, f.id
, f.foo_id
, f.carryover_id
, ISNULL(f.amount,0) as amount
, ISNULL(f.amount,0) as totalAmount
FROM #fooBar as f
WHERE f.rowNmbr = 1
UNION ALL
SELECT f.rowNmbr
, f.id
, f.foo_id
, f.carryover_id
, ISNULL(f.amount,0) as amount
, CAST((ISNULL(f.amount,0)
+ ISNULL(s.totalAmount,0)) as decimal) as totalAmount
FROM #fooBar as f
INNER JOIN summarizedFoo as s
ON f.carryover_id = s.carryover_id
AND f.rowNmbr = s.rowNmbr +1
)
SELECT rowNmbr, id, foo_id, carryover_id, amount, totalAmount
FROM summarizedFoo
I did this in T-SQL, but to make this work in your fiddler
Here is the PostgreSQL version:
Create a fooBar table (could be a view):
INSERT INTO fooBar
SELECT CAST(b.id as INTEGER)
, CAST(foo_id as INTEGER)
, CAST(CASE WHEN f.carryover_id is NULL THEN foo_id ELSE f.carryover_id END as INTEGER) as carryover_id
, CAST(b.amount as DECIMAL)
, CAST(ROW_NUMBER() OVER(PARTITION BY CASE WHEN f.carryover_id is NULL THEN foo_id ELSE f.carryover_id END ORDER BY b.id asc) as INTEGER) as rowNmbr
FROM bar as b
INNER JOIN foo as f
ON b.foo_id = f.id;
Here is the WITH RECURSIVE:
WITH RECURSIVE summarizedFoo(rowNmbr, id, foo_id, carryover_id, amount, totalAmount)
AS
(
SELECT f.rowNmbr, f.id, f.foo_id, f.carryover_id
, f.amount
, f.amount
FROM fooBar as f
WHERE f.rowNmbr = 1
UNION ALL
SELECT f.rowNmbr, f.id, f.foo_id, f.carryover_id
, f.amount
, f.amount + s.totalAmount
FROM fooBar as f
INNER JOIN summarizedFoo as s
ON f.carryover_id = s.carryover_id
AND f.rowNmbr = s.rowNmbr +1
)
SELECT rowNmbr, id, foo_id, carryover_id, amount, totalAmount
FROM summarizedFoo
I tested in SSMS(T-SQL version) and Fiddler(PostgreSQL), and verified the results in Excel.
Here is Fiddler of the solution:
http://sqlfiddle.com/#!15/a7822/3
The trick is to populate a table with source > target pairs, then to use that table to calculate the total amount:
CREATE RECURSIVE VIEW leaf_view(target_id, source_id) AS (
SELECT id, id FROM foo
UNION ALL
SELECT leaf_view.target_id, foo.id
FROM leaf_view
JOIN foo ON foo.carryover_id = leaf_view.source_id
);
CREATE VIEW foo_view(id, total) AS
SELECT leaf_view.target_id, SUM(bar.amount)
FROM leaf_view
LEFT JOIN bar ON leaf_view.source_id = bar.foo_id
GROUP BY leaf_view.target_id;
http://sqlfiddle.com/#!15/6834d/62
I owe this answer to RhodiumToad in #postgresql on freenode. Note that this will have problems for large foo since the optimizer generally can't work on recursive queries.
It looks like you want to have a cumulative running total amount. You could get this with a self-join, or a sub query, e.g:
select
id,
amount,
(select sum amount from foo b where b.id <= a.id ) as cumulative
from foo a
or
select
a.id,
a.amount,
sum(b.amount) as cumulative
from foo a
join foo b on b.id <= a.id
group by a.id, a.amount
Editing my answer as below.. I realized you are trying to do something recursive, does this help?? It'd really help if you gave a sample input and the output that you are expecting..
WITH RECURSIVE foo_view(id, total) AS (
SELECT id, amount from foo;
UNION ALL
SELECT foo_view.id, sum(foo_view.total+foo.amount)
FROM foo
JOIN
foo_view
ON
foo_view.id = foo.carryover_id
)
SELECT * from foo_view