BAQ difference in Pilot compared to LIVE

Brandon, Do you want to see the BAQ Export or the Query Phrase?

This will fail if something is tripping it up.

Can you try tryparse()

    CASE WHEN TRY_PARSE(LastTask.Key1 AS int USING 'en-US') IS NULL  
        THEN '0'  
        ELSE convert(int,LastTask.Key1 )

https://learn.microsoft.com/en-us/sql/t-sql/functions/try-parse-transact-sql?view=sql-server-ver16

1 Like

Query phrase is fine.

/*
 * Disclaimer!!!
 * This is not a real query being executed, but a simplified version for general vision.
 * Executing it with any other tool may produce a different result.
 */
 
select 
	[QuoteHed].[QuoteNum] as [QuoteHed_QuoteNum],
	[QuoteHed].[EntryDate] as [QuoteHed_EntryDate],
	[QuoteHed].[Reference] as [QuoteHed_Reference],
	[Customer].[CustID] as [Customer_CustID],
	[Customer].[Name] as [Customer_Name],
	(iif(QuoteHed.UseOTS = 'true', 'OTS End User', EndUserCust.CustID)) as [Calculated_EndUserID],
	(iif(QuoteHed.UseOTS = 'true', QuoteHed.OTSName, EndUserCust.Name)) as [Calculated_EndUserName],
	(iif(QuoteHed.UseOTS = 'true', QuoteHed.OTSState, ShipTo.State)) as [Calculated_EndUserState],
	(iif(QuoteHed.UseOTS = 'true', OTS_EndUserCounty.Description, Country.Description)) as [Calculated_EndUserCountry],
	[QuoteDtl].[PartNum] as [QuoteDtl_PartNum],
	[QuoteDtl].[LineDesc] as [QuoteDtl_LineDesc],
	[QSalesRP].[Name] as [QSalesRP_Name],
	[Task_Last].[TaskDescription] as [Task_Last_TaskDescription],
	(QuoteHed.DocTotalPotential + QuoteHed.DocTotalMiscAmt + QuoteHed.DocTax) as [Calculated_TotalQuote_calc],
	[QuoteDtl].[Quoted] as [QuoteDtl_Quoted],
	[SalesCat].[Description] as [SalesCat_Description],
	[QuoteDtl].[Industry_c] as [QuoteDtl_Industry_c],
	[Task_Last].[Conclusion] as [Task_Last_Conclusion],
	[OrderDtl].[OrderNum] as [OrderDtl_OrderNum],
	(iif(Task_Last.Conclusion = 'WIN', Reason1.Description, iif(Task_Last.Conclusion = 'LOSE', Reason.Description, ''))) as [Calculated_WinLoseReason],
	[MktgCamp].[CampDescription] as [MktgCamp_CampDescription],
	[MktgEvnt].[EvntDescription] as [MktgEvnt_EvntDescription],
	[QuoteDtl].[XPartNum] as [QuoteDtl_XPartNum],
	[ProdGrup].[Description] as [ProdGrup_Description],
	[QSalesRPAgent].[Name] as [QSalesRPAgent_Name],
	[QuoteHed].[ExpectedClose] as [QuoteHed_ExpectedClose],
	[QuoteCnt].[Name] as [QuoteCnt_Name],
	[Task_Last].[DueDate] as [Task_Last_DueDate],
	[QuoteHed].[CurrentStage] as [QuoteHed_CurrentStage],
	(iif(QuotesWithLeads.Calculated_LastLeadTaskSeqNum > 0, 1, 0)) as [Calculated_StartedAsLead],
	[LeadConversionDate].[CreateDate] as [LeadConversionDate_CreateDate],
	[QuoteHed].[QuoteRisk_c] as [QuoteHed_QuoteRisk_c],
	[QuoteHed].[QuoteRiskNotes_c] as [QuoteHed_QuoteRiskNotes_c],
	[Customer].[CustNum] as [Customer_CustNum]
from Erp.QuoteHed as QuoteHed
inner join Erp.QuoteDtl as QuoteDtl on 
	QuoteHed.Company = QuoteDtl.Company
	and QuoteHed.QuoteNum = QuoteDtl.QuoteNum
	and ( QuoteDtl.QuoteLine = 1  and not QuoteDtl.SalesCatID = 'PART'  and QuoteDtl.SalesCatID = @SalesCategory  )

left outer join Erp.SalesCat as SalesCat on 
	QuoteDtl.Company = SalesCat.Company
	and QuoteDtl.SalesCatID = SalesCat.SalesCatID
left outer join Erp.OrderDtl as OrderDtl on 
	QuoteDtl.Company = OrderDtl.Company
	and QuoteDtl.QuoteNum = OrderDtl.QuoteNum
	and ( OrderDtl.OrderLine = 1  )

inner join Erp.ProdGrup as ProdGrup on 
	QuoteDtl.Company = ProdGrup.Company
	and QuoteDtl.ProdCode = ProdGrup.ProdCode
inner join Erp.Customer as Customer on 
	QuoteHed.Company = Customer.Company
	and QuoteHed.CustNum = Customer.CustNum
inner join Erp.QSalesRP as QSalesRP on 
	QuoteHed.Company = QSalesRP.Company
	and QuoteHed.QuoteNum = QSalesRP.QuoteNum
	and ( QSalesRP.PrimeRep = TRUE  and QSalesRP.SalesRepCode = @PrimarySales  )

left outer join Erp.Customer as EndUserCust on 
	QuoteHed.Company = EndUserCust.Company
	and QuoteHed.ShipToCustNum = EndUserCust.CustNum
left outer join Erp.ShipTo as ShipTo on 
	QuoteHed.Company = ShipTo.Company
	and QuoteHed.ShipToCustNum = ShipTo.CustNum
	and QuoteHed.ShipToNum = ShipTo.ShipToNum
left outer join Erp.Country as Country on 
	ShipTo.Company = Country.Company
	and ShipTo.CountryNum = Country.CountryNum
left outer join Erp.Country as OTS_EndUserCounty on 
	OTS_EndUserCounty.Company = QuoteHed.Company
	and OTS_EndUserCounty.CountryNum = QuoteHed.OTSCountryNum
left outer join Erp.MktgCamp as MktgCamp on 
	QuoteHed.Company = MktgCamp.Company
	and QuoteHed.MktgCampaignID = MktgCamp.MktgCampaignID
left outer join Erp.MktgEvnt as MktgEvnt on 
	QuoteHed.Company = MktgEvnt.Company
	and QuoteHed.MktgCampaignID = MktgEvnt.MktgCampaignID
	and QuoteHed.MktgEvntSeq = MktgEvnt.MktgEvntSeq
inner join  (select 
	[LastTask].[Company] as [LastTask_Company],
	[LastTask].[Key1] as [LastTask_Key1],
	(MAX(LastTask.TaskSeqNum)) as [Calculated_LTaskSeq]
from Erp.Task as LastTask
group by [LastTask].[Company],
	[LastTask].[Key1])  as LastTask1 on 
	QuoteHed.Company = LastTask1.LastTask_Company
	and QuoteHed.QuoteNum = LastTask1.LastTask_Key1
inner join Erp.Task as Task_Last on 
	LastTask1.LastTask_Company = Task_Last.Company
	and LastTask1.LastTask_Key1 = Task_Last.Key1
	and LastTask1.Calculated_LTaskSeq = Task_Last.TaskSeqNum
	and ( Task_Last.Conclusion = @WinLostOpen  and Task_Last.TaskID = @CurrentTask  )

left outer join Erp.Reason as Reason on 
	Task_Last.Company = Reason.Company
	and Task_Last.ReasonCode = Reason.ReasonCode
	and ( Reason.ReasonType = 'L'  )

left outer join Erp.Reason as Reason1 on 
	Task_Last.Company = Reason1.Company
	and Task_Last.ReasonCode = Reason1.ReasonCode
	and ( Reason1.ReasonType = 'W'  )

left outer join Erp.QSalesRP as QSalesRPAgent on 
	QuoteHed.Company = QSalesRPAgent.Company
	and QuoteHed.QuoteNum = QSalesRPAgent.QuoteNum
	and ( QSalesRPAgent.RoleCode = 'AGENT'  )

left outer join Erp.QuoteCnt as QuoteCnt on 
	QuoteHed.Company = QuoteCnt.Company
	and QuoteHed.QuoteNum = QuoteCnt.QuoteNum
	and ( QuoteCnt.PrimeContact = 1  )

left outer join  (select 
	[Task].[Company] as [Task_Company],
	[Task].[TaskQuoteNum] as [Task_TaskQuoteNum],
	(max(Task.TaskSeqNum) + 10) as [Calculated_LastLeadTaskSeqNum]
from Erp.TaskSDtl as TaskSDtl
inner join Erp.Task as Task on 
	TaskSDtl.Company = Task.Company
	and TaskSDtl.TaskSetID = Task.TaskSetID
	and TaskSDtl.TaskSetSeq = Task.TaskSetSeq
where (TaskSDtl.CurrentStage = 'LEAD')
group by [Task].[Company],
	[Task].[TaskQuoteNum])  as QuotesWithLeads on 
	QuoteHed.Company = QuotesWithLeads.Task_Company
	and QuoteHed.QuoteNum = QuotesWithLeads.Task_TaskQuoteNum
left outer join Erp.Task as LeadConversionDate on 
	QuotesWithLeads.Task_Company = LeadConversionDate.Company
	and QuotesWithLeads.Task_TaskQuoteNum = LeadConversionDate.TaskQuoteNum
	and QuotesWithLeads.Calculated_LastLeadTaskSeqNum = LeadConversionDate.TaskSeqNum
where (QuoteHed.CustNum = @QuotedToCustomer  and QuoteHed.ShipToCustNum = @EndUserCustomer  and QuoteHed.EntryDate >= @QuoteCreateAfter  and QuoteHed.EntryDate <= @QuoteCreateBefore  and QuoteHed.QuoteRisk_c >= @RiskGreaterOREqual)

on this join add in a conversion to the quote num to make it a character field.

This is obviously a silly example, but you can do they joins like this for the quotenum to key 1, and you should stop getting the error. (you only need the conversion on the quote num, but you get the point)

I tried using the cast and I still get the BAD SQL Statement:

Not sure, just grasping at straws here, maybe try extending to nvarchar(30) rather than just 8. I have no clue here.

I actually tried it at 50 with the same error.


I used 50 because the LastTask_Key1 is formatted as x(50):

Can you remove the company table temporarily out of the query? Since casting the join didn’t fix it, I’m guessing it has to do with security, and that’s the table that triggers security.

Also, just to cover the bases here, this is NOT an updated BAQ, correct?

Here’s another thing to try. (no idea if it will have an effect) but this is an option to use a different type of security. (grasping at straws here).

Task should have a TaskQuoteNum field in it… that if it were exposed in the subquery instead of Key1, that might help?

Dr. Dan nailed it!
So I changed the references to Key1 on Task in my subquery and top query and rewrote one formula.
Here is what I changed:
Originally I had this:

I changed it to this:
image

The first time I tried this I still got an error, so I DELETED the calculated field and recreated it with the same EXACT formula:
image

Then I changed the table links in the Top Query.
Originally the first link looked like this:

And I changed the first link to this:

Then I changed the second link from this:

To this:

And my BAD SQL statement error went away.

So now the question is…Why does this work in Pilot but fails in LIVE?

It’s a data issue, which can be intermittent dependent on the SQL plan. Depending on what order things are queried and pared down, it may or may not run into the bad data. A SQL can have a mind of it’s own when it makes execution plans. So since they are 2 different databases, with slightly different data, it can make a vastly different plan. Then on top of that, in the name of efficiency, it will many times hold onto the old plan and not make the new one even with vastly different parameters. That’s called parameter sniffing, which can be a problem.

But even if it’s not specifically parameter sniffing, the states of the indexes will cause a difference in plans as well.

For grins and giggles, can you create a new query just on key1 that tries to parse to int? (like I showed earlier in this thread). I bet you find a field in there that doesn’t parse.

Do a calculated field with this.

    CASE WHEN TRY_PARSE(LastTask.Key1 AS decimal USING 'en-US') IS NULL  
        THEN 'True'  
        ELSE 'False' 
END

then another with

count(1)

Then group by the calculated field (so you’ll only have 2 fields for the whole BAQ) and see if you get and Trues? And how many you get?

Because I think this is interesting… I’m going to explain farther how a data issue could be intermittent with different SQL plans.

So let’s take this simple table as an example. Key1 is a character field but it houses numbers, usually. However notice the first record for C2 has a “A” in the field. So that won’t translate to an integer.

Company Key1
C1 1
C1 5
C1 345
C1 345
C1 32
C1 6634
C1 663
C2 A19685
C2 1
C2 51
C2 635
C2 185
C2 156
C2 23465
C2 634

So say I’m making a query, where I’m only looking at Company C1 data. I see there are no Characters in the fields for C1 so I should be able to translate to ints no problem.

select convert(key1 as int) from myTable
where Company = "C1"

This will pare down the table to just the C1 records.

Company Key1
C1 1
C1 5
C1 345
C1 345
C1 32
C1 6634
C1 663

Now lets say I want only the key1.

select convert(key1 as int) from myTable
where Company = "C1" and Key1 = 1

This is what we expect in the end, but it doesn’t get there in one step.

Company Key1
C1 1

If I do company, then key

step 1

Company Key1
C1 1
C1 5
C1 345
C1 345
C1 32
C1 6634
C1 663
C2 A19685 It doesn’t need to read key1 to exclude this record
C2 1
C2 51
C2 635
C2 185
C2 156
C2 23465
C2 634
step 2
Company Key1
C1 1
C1 5
C1 345
C1 345
C1 32
C1 6634
C1 663

We are ok when the program tries to do it in this order.

But, while most programming languages will do the thing in the order they are typed, SQL tries to optimize and thinks it’s smarter than you, so it might not do it in that order. It might try to filter based on the key1 value before it limits my Company.

step 1.

Company Key1
C1 1
C1 5
C1 345
C1 345
C1 32
C1 6634
C1 663
C2 A19685 while trying to read this, it fails
C2 1
C2 51
C2 635
C2 185
C2 156
C2 23465
C2 634

To do that, it will read all of the key1 values and try to compare it to an integer, and the first record in C2 will puke, because it can’t convert that to an integer to compare the 2.

In this simple example, you would simply put single quotes around the 1, but if you are doing the limiting by joins, then it can’t do that.

Why does it do what it does? I’m not educated enough to definitively say, but it’s affected by index statistics, and prior queries run. And the things that affect them are very touchy and can give you wildly varying plans with seemingly inconsequential changes. So it’s quite likely that you’ll get different results with different databases.

3 Likes

Brandon,
I got Zero True.

I love to learn something new, so thank you for your input on this.

Damn, I was sure it was that.

I still think it’s a data issue somewhere…

If we go back to the very first post where this is the error, I still kind of think that it has to do with security.

And this “Fix” could simply be a new plan since you changed enough that SQL is doing it differently and doesn’t run into the problem.

Frustrating though when we can’t find the murder weapon.

WAIT…I think I did something wrong…It may have one True.
image

1 Like

Happy Aww GIF by MCDM

See if you can find it. Let me know if you need help making the query to find it.

I need help finding it…I am not good with the Group By…

Remove the group by and the count field. Bring in your key field, and whatever fields you need to identify the record. Then make that an inner sub query, make a new top level, bring in the subquery and filter the “Table” but the calculated field to only show “True”.

Edit: or even easier, just replace “True” with the key field in your calculated field. Then you don’t have to change anything else.

image