question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to avoid Cte simplification

See original GitHub issue

Sometimes when I’m composing a tree of Ctes, I get cte duplicates. I think that the issue is caused by some sort of Cte simplification done by linq2db. For example if a have a Cte like this:

-- Wip Oracle.Managed Oracle12
DECLARE @startDateTime TimeStamp -- DateTime
SET     @startDateTime = TO_TIMESTAMP('2019-07-22 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')
DECLARE @endDateTime TimeStamp -- DateTime
SET     @endDateTime = TO_TIMESTAMP('2019-07-23 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')

WITH SerialTested
(
	Site,
	Sfc,
	SfcBo,
	ShopOrderBo,
	ItemBo,
	MasterOperationBo,
	ResourceBo,
	WorkCenterBo,
	DateTime,
	Type
)
AS
(
	SELECT
		zmeHstTest.SITE as Site,
		zmeHstTest.SFC as Sfc,
		zmeHstTest.SFC_BO as SfcBo,
		zmeHstTest.SHOP_ORDER_BO as ShopOrderBo,
		zmeHstTest.ITEM_BO as ItemBo,
		zmeHstTest.OPERATION_BO as MasterOperationBo,
		zmeHstTest.RESOURCE_BO as ResourceBo,
		zmeHstTest.WORK_CENTER_BO as WorkCenterBo,
		zmeHstTest.DATE_TIME as DateTime,
		zmeHstTest.TYPE as Type_1
	FROM
		ZME_HST_TEST zmeHstTest
	WHERE
		zmeHstTest.ORT = 'false' AND zmeHstTest.DATE_TIME >= CAST(:startDateTime AS DATE) AND
		zmeHstTest.DATE_TIME <= CAST(:endDateTime AS DATE)
)
SELECT
	t1.Site,
	t1.Sfc,
	t1.SfcBo,
	t1.ShopOrderBo,
	t1.ItemBo,
	t1.MasterOperationBo,
	t1.ResourceBo,
	t1.WorkCenterBo,
	t1.DateTime,
	t1.Type as Type_1
FROM
	SerialTested t1

when I use it in another Cte I get:

-- Wip Oracle.Managed Oracle12
DECLARE @startDateTime TimeStamp -- DateTime
SET     @startDateTime = TO_TIMESTAMP('2019-07-22 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')
DECLARE @endDateTime TimeStamp -- DateTime
SET     @endDateTime = TO_TIMESTAMP('2019-07-23 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')

WITH SerialTested (MasterOperationBo, Site)
AS
(
	SELECT
		zmeHstTest.OPERATION_BO as MasterOperationBo,
		zmeHstTest.SITE as Site
	FROM
		ZME_HST_TEST zmeHstTest
	WHERE
		zmeHstTest.ORT = 'false' AND zmeHstTest.DATE_TIME >= CAST(:startDateTime AS DATE) AND
		zmeHstTest.DATE_TIME <= CAST(:endDateTime AS DATE)
),
DistinctOperationBo (MasterOperationBo, Site)
AS
(
	SELECT DISTINCT
		serialTested_1.MasterOperationBo,
		serialTested_1.Site
	FROM
		SerialTested serialTested_1
)
SELECT
	t1.MasterOperationBo,
	t1.Site
FROM
	DistinctOperationBo t1

The problem is that in the final query I get 2 duplicates of SerialTested, SerialTested0 and SerialTested1 with a duplicate of corresponding parameters:

-- Wip Oracle.Managed Oracle12
DECLARE @startDateTime_1 TimeStamp -- DateTime
SET     @startDateTime_1 = TO_TIMESTAMP('2019-07-22 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')
DECLARE @endDateTime_1 TimeStamp -- DateTime
SET     @endDateTime_1 = TO_TIMESTAMP('2019-07-23 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')
DECLARE @startDateTime_2 TimeStamp -- DateTime
SET     @startDateTime_2 = TO_TIMESTAMP('2019-07-22 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')
DECLARE @endDateTime_2 TimeStamp -- DateTime
SET     @endDateTime_2 = TO_TIMESTAMP('2019-07-23 07:34:52.000000', 'YYYY-MM-DD HH24:MI:SS.FF6')

WITH SerialTested0
(
	SfcBo,
	MasterOperationBo,
	ShopOrderBo,
	ResourceBo,
	WorkCenterBo,
	Site,
	Sfc,
	DateTime,
	Type
)
AS
(
	SELECT
		zmeHstTest_1.SFC_BO as SfcBo,
		zmeHstTest_1.OPERATION_BO as MasterOperationBo,
		zmeHstTest_1.SHOP_ORDER_BO as ShopOrderBo,
		zmeHstTest_1.RESOURCE_BO as ResourceBo,
		zmeHstTest_1.WORK_CENTER_BO as WorkCenterBo,
		zmeHstTest_1.SITE as Site,
		zmeHstTest_1.SFC as Sfc,
		zmeHstTest_1.DATE_TIME as DateTime,
		zmeHstTest_1.TYPE as Type_1
	FROM
		ZME_HST_TEST zmeHstTest_1
	WHERE
		zmeHstTest_1.ORT = 'false' AND zmeHstTest_1.DATE_TIME >= CAST(:startDateTime_1 AS DATE) AND
		zmeHstTest_1.DATE_TIME <= CAST(:endDateTime_1 AS DATE)
),
SerialTested1 (MasterOperationBo, Site)
AS
(
	SELECT
		zmeHstTest_2.OPERATION_BO as MasterOperationBo,
		zmeHstTest_2.SITE as Site
	FROM
		ZME_HST_TEST zmeHstTest_2
	WHERE
		zmeHstTest_2.ORT = 'false' AND zmeHstTest_2.DATE_TIME >= CAST(:startDateTime_2 AS DATE) AND
		zmeHstTest_2.DATE_TIME <= CAST(:endDateTime_2 AS DATE)
),
ItemGroupMembers (RowNumber, ItemBo, ItemGroupBo)
AS
(
	SELECT
		ROW_NUMBER() OVER(PARTITION BY itemGroupMember.ITEM_BO ORDER BY itemGroupMember.ITEM_GROUP_BO) as RowNumber,
		itemGroupMember.ITEM_BO as ItemBo,
		itemGroupMember.ITEM_GROUP_BO as ItemGroupBo
	FROM
		ITEM_GROUP_MEMBER itemGroupMember
),
FindRouterGroups
(
	Sequence,
	LastRouterSequence,
	MasterOperationBo,
	ShopOrderBo,
	ResourceBo,
	WorkCenterBo,
	Site,
	RouterBo,
	Sfc,
	SfcBo,
	DateTime,
	Type
)
AS
(
	SELECT
		sfcRouter.SEQUENCE as Sequence_1,
		MAX(sfcRouter.SEQUENCE) OVER(PARTITION BY sfcRouter.SFC_ROUTING_BO) as LastRouterSequence,
		serialTested_1.MasterOperationBo,
		serialTested_1.ShopOrderBo,
		serialTested_1.ResourceBo,
		serialTested_1.WorkCenterBo,
		serialTested_1.Site,
		router_1.HANDLE as RouterBo,
		serialTested_1.Sfc,
		serialTested_1.SfcBo,
		serialTested_1.DateTime,
		serialTested_1.Type as Type_1
	FROM
		SerialTested0 serialTested_1
			INNER JOIN SFC_ROUTING sfcRouting ON sfcRouting.SFC_BO = serialTested_1.SfcBo
			INNER JOIN SFC_ROUTER sfcRouter ON sfcRouter.SFC_ROUTING_BO = sfcRouting.HANDLE
			INNER JOIN ROUTER router_1 ON router_1.HANDLE = sfcRouter.ROUTER_BO
	WHERE
		(sfcRouter.COMPLETED = 'false' AND sfcRouter.IN_USE = 'true' OR sfcRouter.COMPLETED = 'true')
),
DistinctOperationBo (MasterOperationBo, Site)
AS
(
	SELECT DISTINCT
		serialTested_2.MasterOperationBo,
		serialTested_2.Site
	FROM
		SerialTested1 serialTested_2
),
FirstItemGroupMember (ItemBo, ItemGroupBo)
AS
(
	SELECT
		itemGroupMembers_1.ItemBo,
		itemGroupMembers_1.ItemGroupBo
	FROM
		ItemGroupMembers itemGroupMembers_1
	WHERE
		itemGroupMembers_1.RowNumber = 1
),
FindRouter
(
	MasterOperationBo,
	ShopOrderBo,
	ResourceBo,
	WorkCenterBo,
	Site,
	RouterBo,
	Sfc,
	SfcBo,
	DateTime,
	Type
)
AS
(
	SELECT
		findRouterGroups_1.MasterOperationBo,
		findRouterGroups_1.ShopOrderBo,
		findRouterGroups_1.ResourceBo,
		findRouterGroups_1.WorkCenterBo,
		findRouterGroups_1.Site,
		findRouterGroups_1.RouterBo,
		findRouterGroups_1.Sfc,
		findRouterGroups_1.SfcBo,
		findRouterGroups_1.DateTime,
		findRouterGroups_1.Type as Type_1
	FROM
		FindRouterGroups findRouterGroups_1
	WHERE
		findRouterGroups_1.Sequence = findRouterGroups_1.LastRouterSequence
),
DistinctOperationData
(
	MasterOperationBo,
	OperationBo,
	Operation,
	Revision,
	Description
)
AS
(
	SELECT
		distinctOperationBo_1.MasterOperationBo,
		operation_2.HANDLE as OperationBo,
		operation_2.OPERATION as Operation_1,
		operation_2.REVISION as Revision,
		operation_2.DESCRIPTION as Description
	FROM
		DistinctOperationBo distinctOperationBo_1
			INNER JOIN OPERATION operation_2 ON distinctOperationBo_1.Site = operation_2.SITE AND operation_2.HANDLE LIKE REPLACE(distinctOperationBo_1.MasterOperationBo, '#', '%') AND operation_2.CURRENT_REVISION = 'true'
),
RouterOperationTestCategory (MasterOperationBo, RouterBo, TestCategory)
AS
(
	SELECT
		distinctOperationBo_2.MasterOperationBo,
		routerStep.ROUTER_BO as RouterBo,
		customFields_1.VALUE as TestCategory
	FROM
		DistinctOperationBo distinctOperationBo_2
			INNER JOIN ROUTER_OPERATION routerOperation ON distinctOperationBo_2.MasterOperationBo = routerOperation.OPERATION_BO
			INNER JOIN CUSTOM_FIELDS customFields_1 ON customFields_1.HANDLE = routerOperation.HANDLE AND customFields_1.ATTRIBUTE = 'TEST_CATEGORY'
			INNER JOIN ROUTER_STEP routerStep ON routerStep.HANDLE = routerOperation.ROUTER_STEP_BO
),
GetAdditionalData
(
	Site,
	SiteDescription,
	Sfc,
	SfcBo,
	Qty,
	ShopOrderBo,
	ShopOrder,
	ItemBo,
	Item,
	ItemDescription,
	ItemRevision,
	ItemGroup,
	ItemGroupDescription,
	ProductLine,
	ProductGroup,
	ProductHierarchy,
	OperationBo,
	Operation,
	OperationRevision,
	OperationDescription,
	ResourceBo,
	Resrce,
	ResrceDescription,
	WorkCenterBo,
	WorkCenter,
	WorkCenterDescription,
	Line,
	LineDescription,
	DateTime,
	Type,
	TestCategory
)
AS
(
	SELECT
		findRouter_1.Site,
		site_1.DESCRIPTION as SiteDescription,
		findRouter_1.Sfc,
		findRouter_1.SfcBo,
		1 as Qty,
		findRouter_1.ShopOrderBo,
		shopOrder_1.SHOP_ORDER as ShopOrder,
		item_1.HANDLE as ItemBo,
		item_1.ITEM as Item,
		item_1.DESCRIPTION as ItemDescription,
		item_1.REVISION as ItemRevision,
		itemGroup_1.ITEM_GROUP as ItemGroup,
		itemGroup_1.DESCRIPTION as ItemGroupDescription,
		customFields_2.VALUE as ProductLine,
		customFields2.VALUE as ProductGroup,
		customFields3.VALUE as ProductHierarchy,
		distinctOperationData_1.OperationBo,
		distinctOperationData_1.Operation as Operation_1,
		distinctOperationData_1.Revision as OperationRevision,
		distinctOperationData_1.Description as OperationDescription,
		findRouter_1.ResourceBo,
		resrce_1.RESRCE as Resrce,
		resrce_1.DESCRIPTION as ResrceDescription,
		findRouter_1.WorkCenterBo,
		workCenter_1.WORK_CENTER as WorkCenter,
		workCenter_1.DESCRIPTION as WorkCenterDescription,
		workCenter2.WORK_CENTER as Line,
		workCenter2.DESCRIPTION as LineDescription,
		findRouter_1.DateTime,
		findRouter_1.Type as Type_1,
		routerOperationTestCategory_1.TestCategory
	FROM
		FindRouter findRouter_1
			INNER JOIN DistinctOperationData distinctOperationData_1 ON distinctOperationData_1.MasterOperationBo = findRouter_1.MasterOperationBo
			INNER JOIN SHOP_ORDER shopOrder_1 ON shopOrder_1.HANDLE = findRouter_1.ShopOrderBo
			INNER JOIN ITEM item_1 ON item_1.HANDLE = shopOrder_1.ITEM_BO
			INNER JOIN RESRCE resrce_1 ON resrce_1.HANDLE = findRouter_1.ResourceBo
			INNER JOIN WORK_CENTER workCenter_1 ON workCenter_1.HANDLE = findRouter_1.WorkCenterBo
			INNER JOIN SITE site_1 ON site_1.SITE = findRouter_1.Site
			LEFT JOIN RouterOperationTestCategory routerOperationTestCategory_1 ON routerOperationTestCategory_1.MasterOperationBo = findRouter_1.MasterOperationBo AND routerOperationTestCategory_1.RouterBo = findRouter_1.RouterBo
			LEFT JOIN WORK_CENTER_MEMBER workCenterMember ON workCenterMember.WORK_CENTER_OR_RESOURCE_GBO = workCenter_1.HANDLE
			LEFT JOIN WORK_CENTER workCenter2 ON workCenter2.HANDLE = workCenterMember.WORK_CENTER_BO
			LEFT JOIN FirstItemGroupMember firstItemGroupMember_1 ON firstItemGroupMember_1.ItemBo = item_1.HANDLE
			LEFT JOIN ITEM_GROUP itemGroup_1 ON itemGroup_1.HANDLE = firstItemGroupMember_1.ItemGroupBo
			LEFT JOIN CUSTOM_FIELDS customFields_2 ON customFields_2.HANDLE = item_1.HANDLE AND customFields_2.ATTRIBUTE = 'PRODUCT_LINE'
			LEFT JOIN CUSTOM_FIELDS customFields2 ON customFields2.HANDLE = item_1.HANDLE AND customFields2.ATTRIBUTE = 'SPART'
			LEFT JOIN CUSTOM_FIELDS customFields3 ON customFields3.HANDLE = item_1.HANDLE AND customFields3.ATTRIBUTE = 'PRDHA'
)
SELECT
	t1.Site,
	t1.SiteDescription,
	t1.Sfc,
	t1.SfcBo,
	t1.ShopOrderBo,
	t1.ShopOrder,
	t1.ItemBo,
	t1.Item,
	t1.ItemDescription,
	t1.ItemRevision,
	t1.ItemGroup,
	t1.ItemGroupDescription,
	t1.ProductLine,
	t1.ProductGroup,
	t1.ProductHierarchy,
	t1.OperationBo,
	t1.Operation as Operation_1,
	t1.OperationRevision,
	t1.OperationDescription,
	t1.ResourceBo,
	t1.Resrce,
	t1.ResrceDescription,
	t1.WorkCenterBo,
	t1.WorkCenter,
	t1.WorkCenterDescription,
	t1.Line,
	t1.LineDescription,
	t1.DateTime,
	t1.Type as Type_1,
	t1.TestCategory
FROM
	GetAdditionalData t1

Is there a way to avoid this type of behavior?

Thank you for your supporto, Filippo.

Environment details

linq2db version: 3.0.0-rc.1984 Database Server: Oracle Database Provider: Oracle.ManagedDataAccess.Core (3.0.0-preview.1) Operating system: Windows 10 .NET Framework:.NET Core 3.1

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:20 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
sdanylivcommented, Jun 8, 2020

Bad idea to cache using SQL text, everything at the end of the projection may change SQL. Linq2db generates CTE fields only if they are needed for final SQL. That’s why generated SQL is highly optimized.

1reaction
sdanylivcommented, Jun 6, 2020

@filippobottega, root of the problem that this can be very specific situation. In some circumstances library can not detect that two the “same” expressions are equal, possibly they were transformed earlier by linq2db itself and has small little difference.

I have created brach #2262 and we can interactively localize problem.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQL Performance Tips #2
Avoiding running on the heap and CTEs vs Temporary Tables ... CTEs can be a major help in most queries, simplifying the development...
Read more >
Common Table Expressions: When and How to Use Them
CTEs, like database views and derived tables, enable users to more easily write and maintain complex queries via increased readability and simplification. This ......
Read more >
Is using a CTE to simplify a GROUP BY bad ...
I have to keep the code in the GROUP BY and the SELECT "in step" Let's assume its a lot more complex than...
Read more >
Key Notes on SQL CTE and Best Practices
Simplified Syntax: CTE provides a simplified syntax for writing complex ... Avoid using nested CTEs, as they can make the query difficult to...
Read more >
How to simplify multiple CTE - sql
1 Answer 1 ... This would avoid multiple passes on the various tables and should run much quicker unless these are highly selective...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found