The multi-part identifier "..." could not be bound - tsql

I get error (The multi-part identifier "f.FormID" could not be bound.) running this query:
select f.FormID, f.Title, fv.UserName
from Forms f join (
SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)
UNION
SELECT FormRelations.ForigenFormID
FROM FormRelations INNER JOIN
Forms ON FormRelations.ForigenFormID = Forms.FormID
WHERE (FormRelations.PrimaryFormID =
(SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)))
) ids
on f.FormID = ids.FormID
LEFT OUTER JOIN (select top 1 UserName, FormID from FormValues where FormID = f.FormID and UserName = #UserName) fv
ON f.FormID = fv.FormID
Please someone help me :(
#bluefeet:
I want such a result:
01304636-FABE-4A3E-9487-A14B012F9A61 item_1 1234567890
C0455E97-788A-4305-876A-A15000CFE928 item_2 1234567890
7719F37E-7021-4ABD-91ED-A15301830324 item_3 1234567890

If you need to use your alias inside of your subquery like that, you might want to look at using the APPLY operator:
select f.FormID, f.Title, fv.UserName
from Forms f
join
(
SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)
UNION
SELECT FormRelations.ForigenFormID
FROM FormRelations
INNER JOIN Forms
ON FormRelations.ForigenFormID = Forms.FormID
WHERE (FormRelations.PrimaryFormID = (SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)))
) ids
on f.FormID = ids.FormID
CROSS APPLY
(
select top 1 UserName, FormID
from FormValues
where FormID = f.FormID
and UserName = #UserName
) fv
Or you can use row_number():
select f.FormID, f.Title, fv.UserName
from Forms f
join
(
SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)
UNION
SELECT FormRelations.ForigenFormID
FROM FormRelations
INNER JOIN Forms
ON FormRelations.ForigenFormID = Forms.FormID
WHERE (FormRelations.PrimaryFormID = (SELECT FormID
FROM Reports
WHERE (ReportID = #ReportID)))
) ids
on f.FormID = ids.FormID
LEFT JOIN
(
select UserName, FormID,
ROW_NUMBER() over(PARTITION by FormID, UserName order by FormID) rn
from FormValues
where UserName = #UserName
) fv
on f.FormID = fv.FormID
and fv.rn = 1

Related

N1QL query dropping records after join with a subquery

The Below Query is dropping records when i join 2 N1QL sub queries -
We are using couchbase and using N1QL queries.
Full Query -
select
t3.appName,
t3.uuid_proj as uuid,
t3.description,
t3.env,
t3.productStatus
from
( select
t1.uuid as uuid_proj ,
t1.appName as appName ,
t1.description as description,
t2.env as env,
t2.productStatus as productStatus
from
(
select
api_external.uuid ,
api_external.data.appName ,
api_external.data.description
from `api_external`
where type = 'partnerApp'
and data.companyId = '70a149da27cc425da86cba890bf5b143' )t1
join
(
select
api_external.data.env,
api_external.data.productStatus,
api_external.data.partnerAppId
from
`api_external`
where type = 'integration' )t2
on t1.uuid = t2.partnerAppId
) as t3
join (
select t4.uuid as uuid_agg , min(t5.env) as env
from
(select api_external.uuid from `api_external` where type = 'partnerApp' and data.companyId = '70a149da27cc425da86cba890bf5b143' )as t4 join
(select api_external.data.env, api_external.data.partnerAppId from `api_external` where type = 'integration' ) as t5
on t4.uuid = t5.partnerAppId
group by t4.uuid
) as t6
on
t3.uuid_proj = t6.uuid_agg and t3.env = t6.env
As you see it has 2 sub queries -
The below subquery gives 16 records -
select
t1.uuid as uuid_proj
from
(
select
api_external.uuid ,
api_external.data.appName ,
api_external.data.description
from `api_external`
where type = 'partnerApp'
and data.companyId = '70a149da27cc425da86cba890bf5b143' )t1
join
(
select
api_external.data.env,
api_external.data.productStatus,
api_external.data.partnerAppId
from
`api_external`
where type = 'integration' )t2
on t1.uuid = t2.partnerAppId
group by t1.uuid
Also the other subquery also gives 16 records -
select t4.uuid as uuid_agg , min(t5.env) as env
from
(select api_external.uuid from `api_external` where type = 'partnerApp' and data.companyId = '70a149da27cc425da86cba890bf5b143' )as t4 join
(select api_external.data.env, api_external.data.partnerAppId from `api_external` where type = 'integration' ) as t5
on t4.uuid = t5.partnerAppId
group by t4.uuid
By Logic join of both the queries on the same grain UUID must also give 16 records . But it gives only 1 .
What am i doing wrong Please help
The query uses many subqueries and hit the issue.
Try following simplified version
CREATE INDEX ix1 ON api_external(data.companyId, uuid, data.appName, data.description) WHERE type = "partnerApp";
CREATE INDEX ix2 ON api_external(data.partnerAppId, data.env, data.productStatus) WHERE type = "integration";
WITH ct3 AS (SELECT t1.uuid, t1.data.appName, t1.data.description,
t2.data.env, t2.data.productStatus
FROM api_external AS t1
JOIN api_external AS t2 ON t1.uuid = t2.data.partnerAppId
WHERE t1.type = "partnerApp"
AND t1.data.companyId = "70a149da27cc425da86cba890bf5b143"
AND t2.type = "integration"
AND t2.data.partnerAppId IS NOT NULL),
ct6 AS ( SELECT t4.uuid AS uuid_agg , MIN(t5.data.env) AS env
FROM api_external AS t4
JOIN api_external AS t5 ON t4.uuid = t5.data.partnerAppId
WHERE t4.type = "partnerApp"
AND t4.data.companyId = "70a149da27cc425da86cba890bf5b143"
AND t5.type = "integration"
AND t5.data.partnerAppId IS NOT NULL
GROUP BY t4.uuid)
SELECT t3.*
FROM ct3 AS t3
JOIN ct6 AS t6 ON t3.uuid = t6.uuid_agg and t3.env = t6.env;
If same results see following works . After JOIN get all the fields of results of MIN env record each group
SELECT m[1].*
FROM api_external AS t4
JOIN api_external AS t5 ON t4.uuid = t5.data.partnerAppId
WHERE t4.type = "partnerApp"
AND t4.data.companyId = '70a149da27cc425da86cba890bf5b143'
AND t5.type = "integration"
AND t5.data.partnerAppId IS NOT NULL
GROUP BY t4.uuid
LETTING m = MIN([t5.data.env, {t4.uuid, t4.data.appName, t4.data.description,
t5.data.env, t5.data.productStatus}]);

Refine data elements using having clause tsql

I'm trying to pull a dataset that returns records ONLY when there are two QUALIFERs present. I've tried left joins, populating data in temp tables then manipulating something, then numerous having clauses (resulting in subquery selects, and additional groups). I would appreciate any assistance on what I can do further.
Query:
Select E, CASE WHEN QUALIFER = '1' THEN 'NAME1' WHEN QUALIFER = '2' then 'NAME2' ELSE 'FINALNAME' END AS TYPE, count(rt.ID) 'Number '
from TABLE_ONE co (nolock)
join TABLE_TWO rt (nolock)
on co.ID = rt.ID
where co.E in (select * from #tempEmail)
AND convert(date,co.INSERTED_TIMESTAMP)between '1/1/2020' and '8/15/2020'
AND TRANS_STATUS = 'APPROVED'
group by E, QUALIFER
order by E, QUALIFER
Current resultset:
E TYPE Number
FAKEEMAIL1#Gmail NAME1 1
FAKEEMAIL1#Gmail NAME2 1
otheremailj#gmail.com Name1 21
Desired resultset:
E TYPE Number
FAKEEMAIL1#Gmail NAME1 1
FAKEEMAIL1#Gmail NAME2 1
Thank you.
Let's try the below query. I used a temp table to make things more simple for my mind.
if object_id('tempdb.dbo.#email') is not null drop table #email
create table #email
(
email varchar(50),
typeValue varchar(15),
Number int
)
insert into #email(email, typeValue, Number)
Select
E,
CASE WHEN QUALIFER = '1' THEN 'NAME1' WHEN QUALIFER = '2' then 'NAME2' ELSE 'FINALNAME' END AS TYPE,
count(rt.ID) 'Number '
from TABLE_ONE co (nolock)
join TABLE_TWO rt (nolock)
on co.ID = rt.ID
where co.E in (select * from #tempEmail)
AND convert(date,co.INSERTED_TIMESTAMP)between '1/1/2020' and '8/15/2020'
AND TRANS_STATUS = 'APPROVED'
group by E, QUALIFER
select a.email, a.typeValue
from #email a
inner join
(
select email, typeValue, rank() over (partition by email order by typeValue) as typeCount
from #email t
) as b
on b.email = a.email
and b.typeCount > 1

View query without sub selecting T-SQL

so I'm trying to build a view query but I keep failing using only joins so I ended up with this deformation.. Any tips on how I can write this query so I don't have to use 6 subselects?
The FeeSum and PaymentSum can be null, so ideally I do not want those in my result set and I also wouldn't like results where the FeeSum and the PaymentSum are equal.
Quick note: client is the table where the clients informations are stored (name, adress, etc..)
customer has a fk on client and is kind of a shell table for the client that store more information for the client,
payment is a list of all payments a customer did,
order is a list of all orders a customer did.
The goal is to get a list where we can track which customer has open fees to pay, based on the orders. It's a legacy project so don't ask why people can order before paying :)
SELECT
cu.Id as [CustomerId]
, CASE
WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName
END as [Name]
, cl.CustomerNumber
, (SELECT SUM(o.Fee) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [FeeSum]
, (SELECT SUM(p.Amount) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [PaymentSum]
, (SELECT MAX(o.OrderDate) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [LastOrderDate]
, (SELECT MAX(p.PaymentDate) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [LastPaymentDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Reminder' AND f.ClientId = cl.Id) as [LastReminderDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Warning' AND f.ClientId = cl.Id) as [LastWarningDate]
FROM
[publication].[Customer] cu
JOIN
[client].[Client] cl
ON cl.Id = cu.ClientId
WHERE
cu.[Type] = 0
Thanks in advance and I hope I didn't do anything wrong.
Kind regards
You could rewrite the correlated subqueries to instead use joins:
SELECT
cu.Id AS [CustomerId],
CASE WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName END AS [Name],
cl.CustomerNumber,
o.FeeSum,
p.PaymentSum,
o.LastOrderDate,
p.LastPaymentDate,
f.LastReminderDate,
f.LastWarningDate
FROM [publication].[Customer] cu
INNER JOIN [client].[Client] cl
ON cl.Id = cu.ClientId
INNER JOIN
(
SELECT CustomerId, SUM(Fee) AS [FeeSum], MAX(OrderDate) AS [LastOrderDate]
FROM [publication].[Order]
WHERE o.[State] = 2
GROUP BY CustomerId
) o
ON o.CustomerId = cu.Id
INNER JOIN
(
SELECT CustomerId, SUM(Amount) AS [PaymentSum], MAX(PaymentDate) AS [LastPaymentDate]
FROM [publication].[Payment]
WHERE o.[State] = 2
GROUP BY CustomerId
) p
ON p.CustomerId = cu.Id
INNER JOIN
(
SELECT ClientId,
MAX(CASE WHEN TemplateName = 'Reminder' THEN Created END) AS [LastReminderDate],
MAX(CASE WHEN TemplateName = 'Warning' THEN Created END) AS [LastWarningDate]
FROM [client].[File]
GROUP BY ClientId
) f
ON f.ClientId = cl.Id
WHERE
cu.[Type] = 0;

Need to convert Oracle "merge into" query to PostgreSQL

I'm trying to convert the following Oracle query to PostgreSQL:
MERGE into feepay.TRPT_W2_REPORTS TRPT1
USING(
WITH RWS AS
(SELECT PROG.BINCLIENT, TRPT.PUT_DIRECTORY
FROM feepay.program2 PROG
INNER JOIN feepay.TRPT_W2_PROGRAMS TRPT
ON (PROG.BINCLIENT = TRPT.BINCLIENT OR PROG.ISSUER_ID = TRPT.ISSUER_ID))
SELECT TCI.CUSTOMERNAME AS ACCOUNT,
TC.CUSTOMER_ID AS urn,
TC.LAST_NAME,
TC.FIRST_NAME,
TC.DOB,
TCA.ADDRESS
FROM feepay.TAU_CARDNUMBERS TCN
INNER JOIN feepay.TAU_CUSTOMER_CARDNUMBER TCCN ON (TCN.CARDNUMBER_ID = TCCN.CARDNUMBER_ID)
INNER JOIN feepay.TBLCUSTOMERS TC ON (TCCN.CUSTOMER_ID = TC.CUSTOMER_ID)
LEFT JOIN feepay.tau_customeraddress TCA ON (TC.CUSTOMER_ID = TCA.CUSTOMER_ID)
INNER JOIN feepay.TAU_ISSUER TI ON (TI.ISSUER_ID = TCN.ISSUER_ID)
INNER JOIN feepay.TBLCUSTOMERS TCI ON (TCI.CUSTOMER_ID = TI.CUSTOMER_ID)
LEFT JOIN feepay.TRPT_W2_REPORTS TRPT ON (TRPT.URN = TC.CUSTOMER_ID)
WHERE BINCLIENT IN (SELECT BINCLIENT FROM RWS)
AND TC.CUSTOMERNAME NOT IN ('freepay card','svds card')) TRPT2
ON (TRPT1.URN = TRPT2.URN)
WHEN MATCHED THEN
UPDATE SET
TRPT1.ACCOUNT = TRPT2.ACCOUNT,
TRPT1.LAST_NAME = TRPT2.LAST_NAME,
TRPT1.FIRST_NAME = TRPT2.FIRST_NAME,
TRPT1.DOB = TRPT2.DOB,
TRPT1.ADDRESS = TRPT2.ADDRESS,
TRPT1.LAST_UPDATE = now(),
TRPT1.STATUS = 'u' /* uPDATED */
WHEN NOT MATCHED THEN
INSERT (ACCOUNT, URN, LAST_NAME, FIRST_NAME, ISENTITY, DOB, ADDRESS, LAST_UPDATE, STATUS)
VALUES (TRPT2.ACCOUNT, TRPT2.URN, TRPT2.LAST_NAME, TRPT2.FIRST_NAME, 'y', TRPT2.DOB, TRPT2.MIDDLE_NAME,
TRPT2.ADDRESS, now(), 'i');
Unfortunately PostgreSQL does not support MERGE, so I'm really stuck. I hope some database pro out of here can help me with this.
You can use INSERT ON CONFLICT () instead:
insert into feepay.TRPT_W2_REPORTS (ACCOUNT, URN, LAST_NAME, FIRST_NAME, ISENTITY, DOB, ADDRESS, LAST_UPDATE, STATUS)
WITH RWS AS (
SELECT PROG.BINCLIENT, TRPT.PUT_DIRECTORY
FROM feepay.program2 PROG
INNER JOIN feepay.TRPT_W2_PROGRAMS TRPT
ON (PROG.BINCLIENT = TRPT.BINCLIENT OR PROG.ISSUER_ID = TRPT.ISSUER_ID)
)
SELECT TCI.CUSTOMERNAME,
TC.CUSTOMER_ID,
TC.LAST_NAME,
TC.FIRST_NAME,
'Y'
TC.DOB,
TCA.ADDRESS,
now(),
'i'
FROM feepay.TAU_CARDNUMBERS TCN
INNER JOIN feepay.TAU_CUSTOMER_CARDNUMBER TCCN ON (TCN.CARDNUMBER_ID = TCCN.CARDNUMBER_ID)
INNER JOIN feepay.TBLCUSTOMERS TC ON (TCCN.CUSTOMER_ID = TC.CUSTOMER_ID)
LEFT JOIN feepay.tau_customeraddress TCA ON (TC.CUSTOMER_ID = TCA.CUSTOMER_ID)
INNER JOIN feepay.TAU_ISSUER TI ON (TI.ISSUER_ID = TCN.ISSUER_ID)
INNER JOIN feepay.TBLCUSTOMERS TCI ON (TCI.CUSTOMER_ID = TI.CUSTOMER_ID)
LEFT JOIN feepay.TRPT_W2_REPORTS TRPT ON (TRPT.URN = TC.CUSTOMER_ID)
WHERE BINCLIENT IN (SELECT BINCLIENT FROM RWS)
AND TC.CUSTOMERNAME NOT IN ('freepay card','svds card')) TRPT2
ON CONFLICT (URN)
DO UPDATE SET
ACCOUNT = excluded.ACCOUNT,
LAST_NAME = excluded.LAST_NAME,
FIRST_NAME = excluded.FIRST_NAME,
DOB = excluded.DOB,
ADDRESS = excluded.ADDRESS,
LAST_UPDATE = now(),
STATUS = 'u' /* uPDATED */
You need to verify if the columns in the SELECT list match the columns as listed in the INSERT column list.

TSQL Combine Multiple rows and columns

I have a sql server 2008 stored proc with joins which returns multiple rows:
default ~/ / NULL NULL NULL Lorem
default ~/ / NULL NULL NULL Ipsum
I would like to return these two rows as one with the last column combined:
default ~/ / NULL NULL NULL Lorem, Ipsum
My Procedure is below
BEGIN
SET NOCOUNT ON;
SELECT
p.display_name AS Name,
p.url AS Url,
ISNULL(REPLACE(parentPage.url,'~','') + parentPage.alias,REPLACE(p.url,'~','')) as ParentPageURL,
p.page_image AS PageImage,
p.synopsis AS Synopsis,
p.metatitle AS Metatitle,
t.tag_name as tag
FROM page p
LEFT JOIN page parentPage on parentPage.id = p.parentid
LEFT JOIN page_features pf on p.id = pf.pageid and (pf.feature_type = 'TEXT' OR pf.feature_type = 'BLOG')
JOIN dbo.tag_collection_tag tc on tc.tag_collection_id = p.tag_collection_id
JOIN dbo.tag t on t.id = tc.tag_id
JOIN dbo.[Split](UPPER(#tags),',') Split on UPPER(t.tag_name) like '%' + split.Data + '%'
WHERE p.status = 'PUBLISHED'
AND p.include_in_nav = 1
AND (p.pagelevel = #level OR #level IS NULL)
AND (p.section_id = #sectionId OR #sectionId IS NULL)
ORDER BY ISNULL(REPLACE(parentPage.url,'~','') + parentPage.alias,REPLACE(p.url,'~',''))
END
Thank you.
Note if you have a column id in table page. It should be used instead of display_name
;WITH a as
(
SELECT
/*p.id,*/
p.display_name AS Name,
p.url AS Url,
ISNULL(REPLACE(parentPage.url,'~','') + parentPage.alias,REPLACE(p.url,'~','')) as ParentPageURL,
p.page_image AS PageImage,
p.synopsis AS Synopsis,
p.metatitle AS Metatitle,
t.tag_name as tag,
ISNULL(REPLACE(parentPage.url,'~','')
+ parentPage.alias,REPLACE(p.url,'~','')) XXX
FROM page p
LEFT JOIN page parentPage on parentPage.id = p.parentid
LEFT JOIN page_features pf on p.id = pf.pageid and (pf.feature_type = 'TEXT' OR pf.feature_type = 'BLOG')
JOIN dbo.tag_collection_tag tc on tc.tag_collection_id = p.tag_collection_id
JOIN dbo.tag t on t.id = tc.tag_id
JOIN dbo.[Split](UPPER(#tags),',') Split on UPPER(t.tag_name) like '%' + split.Data + '%'
WHERE p.status = 'PUBLISHED'
AND p.include_in_nav = 1
AND (p.pagelevel = #level OR #level IS NULL)
AND (p.section_id = #sectionId OR #sectionId IS NULL)
)
SELECT Name, Url, ParentPageURL, PageImage, Synopsis, Metatitle
,STUFF((
select ',' + [tag]
from a t1
-- I assume display_name is unique. I would use page.id,
-- but I am not sure you have that column
-- t1.id = t.id
where t1.display_name = t.display_name
for xml path(''), type
).value('.', 'varchar(max)'), 1, 1, '') [tags]
from a t
group by Name, Url, ParentPageURL, PageImage, Synopsis, Metatitle
ORDER BY XXX