Providing a column name for the resultant table - sql

I have the below query to extract data in desired format
select
(
select COUNT(serialNumber) as LOTQty
from MobileData
where mobileName = #mobileName and model = #model and LOTQty = #lotQty
)
,(
select COUNT(serialNumber) as FailedQty
from MobileData
where mobileName = #mobileName and model = #model and LOTQty = #lotQty and PreScan = 'FAIL'
)
But when I execute the query it certainly gives the desired result but instead of column names "LotQty" and "FailedQty" it display (No Column Name) and (No Column Name)
I also tried modifying the above query as below but still the result remains same
select
(
select [LotQty] = COUNT(serialNumber)
...
)
,(
select [FailedQty] = COUNT(serialNumber)
...
)
Any help is appreciated. I'm using sql server 2008

You can give colmn name using ALIAS and also you can fetch both count using one query instead of two subqueries.
Try this:
SELECT COUNT(serialNumber) AS LOTQty,
SUM(CASE WHEN PreScan = 'FAIL' THEN 1 ELSE 0 END) AS FailedQty
FROM MobileData
WHERE mobileName = #mobileName AND model = #model AND LOTQty = #lotQty;

The alias name must be outside the subquery
select
(
select COUNT(serialNumber)
from MobileData
where mobileName = #mobileName and model = #model and LOTQty = #lotQty
) as LOTQty
,(
select COUNT(serialNumber)
from MobileData
where mobileName = #mobileName and model = #model and LOTQty = #lotQty and PreScan = 'FAIL'
) as FailedQty

Related

Cannot cast result from Sub-Select to numeric

I am selecting a list of IDs as a sub-query in a condition but it says it cannot convert '123,456' to numeric. The problem occurs in the last line. DB is Sybase-SQL-Anywhere.
SELECT
ISNULL(SUM(a.menge), 0) AS menge,
ISNULL(SUM(a.wert), 0) AS wert
FROM admin.p_ws_ix_kontrakte_ernte_auswertung_jensek a
WHERE
(a.KtrErnteJahr = ? OR ? IS NULL)
AND (
(a.KtrDispoKennz >= ? OR ? IS NULL)
AND
(a.KtrDispoKennz <= ? OR ? IS NULL)
)
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
Remove the LIST():
# replace this:
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
# with this:
AND a.artikelstammid IN (SELECT artikelstammId FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column)
Another option would be an exists/correlated subquery:
# replace this:
AND a.artikelstammid IN ((SELECT LIST(artikelstammId) FROM admin.ws_ix_auswertung_cfg_spalten_artikel WHERE columnId = $column))
# with this:
AND exists (SELECT 1 FROM admin.ws_ix_auswertung_cfg_spalten_artikel b WHERE b.columnId = $column and b.artikelstammId = a.artikelstammid)

Nested in line view Add Column

I have to add a column to this report - the new column name is: uda_value_desc
The code below will give me a result if I enter a PM_ITEM number, I need to insert the code into one of the in line views.
Any help would be appreciated
WITH item_temp AS (SELECT im.item
,uv.uda_value_desc uda_value_desc -----
FROM item_master im
,TABLE(mff_report.parse_strings(:PM_item)) t
, uda_item_lov uil
, uda_values uv
WHERE t.Column_Value = uil.item
and uil.UDA_ID = 511
and uv.uda_id = uil.uda_id
and uv.uda_value = uil.uda_value
and im.item = uil.item
UNION ALL
SELECT im.item
,null
FROM item_master im
,TABLE(mff_report.parse_strings(:PM_item)) t
WHERE t.COLUMN_VALUE = im.item_parent
AND im.item_level = im.tran_level
UNION ALL
SELECT sd.item
,null
FROM skulist_detail sd
,TABLE(mff_report.parse_strings(:PM_item_list)) t
WHERE t.COLUMN_VALUE = sd.skulist
UNION ALL
SELECT ia.item
,null
FROM mffecom.item_attr ia
,TABLE(mff_report.parse_strings(:PM_product_id)) t
WHERE t.COLUMN_VALUE = ia.product_id
UNION ALL
SELECT im.item
,null
FROM item_master im
WHERE :PM_item IS NULL
AND :PM_item_list IS NULL
AND :PM_product_id IS NULL )
SELECT v_item.item_parent
,uda_value_desc
,v_item.item
,mff_report.mff_merch_sql.get_brand_name(v_item.item) brand_name
,v_item.item_desc
,v_selling.product_id
,v_product.product_web_desc
,v_product.product_template
,v_product.romance_copy
,v_selling.selling_point_1
,v_selling.selling_point_2
,v_selling.selling_point_3
,v_selling.selling_point_4
,v_selling.selling_point_5
,v_selling.selling_point_6
,v_selling.selling_point_7
,v_selling.selling_point_8
,v_selling.selling_point_9
,v_selling.selling_point_10
,v_selling.selling_point_11
,v_selling.selling_point_12
,v_selling.selling_point_13
,v_selling.selling_point_14
,v_selling.selling_point_15
,v_selling.selling_point_16
,v_item.vpn
,v_item.diff_1
,v_item.diff1_desc
,v_item.diff_2
,v_item.diff2_desc
,v_item.diff_3
,v_item.diff3_desc
,v_item.diff_4
,v_item.diff4_desc
,v_item.supplier
,v_item.sup_name
,v_product.code_desc fulfillment_method_desc
,v_product.air_ship_restrict
,v_product.do_not_freeze
,v_product.free_shipping
,v_product.refrigerate
,v_product.serial_reqd
,v_product.vaccination
,v_product.is_consumable
,v_product.zero_weight
,v_product.restrict_state
,v_product.no_of_alt_image
,v_product.product_status
,v_product.item_ecom_status
,TO_CHAR(v_product.deactivate_date, 'MM/DD/YYYY') product_deactivate_date
,TO_CHAR(v_product.product_activate_date, 'MM/DD/YYYY') product_activate_date
,TO_CHAR(v_product.item_activate_date, 'MM/DD/YYYY') item_activate_date
,TO_CHAR(v_product.item_deactivate_date, 'MM/DD/YYYY') item_deactivate_date
,v_product.prod_created_by
,TO_CHAR(v_product.prod_created_date, 'MM/DD/YYYY') prod_created_date
,v_product.prod_updated_by
,v_product.item_created_by
,TO_CHAR(v_product.item_created_date, 'MM/DD/YYYY') item_created_date
,v_product.item_updated_by
,v_item.delete_type purge
,v_item.dept
,v_item.class
,v_item.subclass
,mff_orders_sql.buyer_for_item(v_item.item) buyer
,mff_orders_sql.buyer_name_for_item(v_item.item) buyer_name
,v_item.soh
,v_item.length
,v_item.width
,v_item.height
,v_item.weight
,v_variant.variant_id1
,v_variant.value_id1
,v_variant.variant_id2
,v_variant.value_id2
,v_variant.variant_id3
,v_variant.value_id3
,v_variant.variant_id4
,v_variant.value_id4
,v_variant.variant_id5
,v_variant.value_id5
,v_variant.variant_id6
,v_variant.value_id6
FROM (SELECT ia.item
,v_sell.product_id
,MIN(DECODE(row_num,1,selling_point)) selling_point_1
,MIN(DECODE(row_num,2,selling_point)) selling_point_2
,MIN(DECODE(row_num,3,selling_point)) selling_point_3
,MIN(DECODE(row_num,4,selling_point)) selling_point_4
,MIN(DECODE(row_num,5,selling_point)) selling_point_5
,MIN(DECODE(row_num,6,selling_point)) selling_point_6
,MIN(DECODE(row_num,7,selling_point)) selling_point_7
,MIN(DECODE(row_num,8,selling_point)) selling_point_8
,MIN(DECODE(row_num,9,selling_point)) selling_point_9
,MIN(DECODE(row_num,10,selling_point)) selling_point_10
,MIN(DECODE(row_num,11,selling_point)) selling_point_11
,MIN(DECODE(row_num,12,selling_point)) selling_point_12
,MIN(DECODE(row_num,13,selling_point)) selling_point_13
,MIN(DECODE(row_num,14,selling_point)) selling_point_14
,MIN(DECODE(row_num,15,selling_point)) selling_point_15
,MIN(DECODE(row_num,16,selling_point)) selling_point_16
FROM mffecom.item_attr ia
,(SELECT sp.product_id
,row_number () OVER (PARTITION BY sp.product_id ORDER BY sp.selling_point_id) row_num
,sp.selling_point
FROM mffecom.selling_point sp
ORDER BY sp.product_id
,sp.selling_point) v_sell
WHERE ia.product_id = v_sell.product_id
GROUP BY ia.item
,v_sell.product_id) v_selling
,(SELECT NVL(im.item_parent,im.item) item_parent
,im.item
,im.item_desc
,im.dept
,im.class
,im.subclass
,isupp.supplier
,s.sup_name
,isupp.vpn
,miim.stock_on_hand soh
,iscd.length
,iscd.width
,iscd.height
,iscd.weight
,im.diff_1
,di.diff_desc diff1_desc
,im.diff_2
,di2.diff_desc diff2_desc
,im.diff_3
,di3.diff_desc diff3_desc
,im.diff_4
,di4.diff_desc diff4_desc
,dp.delete_type
FROM item_supplier isupp
,sups s
,item_supp_country_dim iscd
,item_master im
,diff_ids di
,diff_ids di2
,diff_ids di3
,diff_ids di4
,daily_purge dp
,merch_item_inv_mv miim
WHERE isupp.item = im.item
AND isupp.item = miim.item (+)
AND isupp.supplier = s.supplier
AND isupp.item = iscd.item
AND isupp.supplier = iscd.supplier
AND isupp.primary_supp_ind = 'Y'
AND iscd.dim_object = 'EA'
AND im.item_level = im.tran_level
AND im.sellable_ind = 'Y'
AND im.diff_1 = di.diff_id (+)
AND im.diff_2 = di2.diff_id (+)
AND im.diff_3 = di3.diff_id (+)
AND im.diff_4 = di4.diff_id (+)
AND im.item = dp.key_value (+)) v_item
,(SELECT ia.item
,pm.product_id
,pm.product_web_desc
,pm.template product_template
,pm.romance_copy
,ia.air_ship_restrict
,ia.do_not_freeze
,ia.free_shipping
,ia.refrigerate
,ia.serial_reqd
,ia.vaccination
,ia.is_consumable
,ia.zero_weight
,pm.no_of_alt_image
,pm.status product_status
,ia.status item_ecom_status
,pm.deactivate_date deactivate_date
,pm.activate_date product_activate_date
,ia.activate_date item_activate_date
,ia.deactivate_date item_deactivate_date
,pm.created_by prod_created_by
,pm.create_datetime prod_created_date
,pm.updated_by prod_updated_by
,ita.created_by item_created_by
,ita.create_date item_created_date
,ia.updated_by item_updated_by
,str.restrict_state
,cd.code_desc
FROM MFFECOM.product_master pm
,MFFECOM.item_attr ia
,MFFECOM.ship_to_restrict str
,rms13.mff_brand mb
,rms13.item_attributes ita
,rms13.code_detail cd
WHERE ia.product_id = pm.product_id
AND ia.item = str.item (+)
AND ia.item = ita.item (+)
AND pm.brand_id = mb.brand_id (+)
AND to_char(ia.fulfillment_method) = cd.code
AND cd.code_type = 'EIFM') v_product
,(SELECT item
,product_id
,MIN(DECODE(row_num,1,variant_id)) variant_id1
,MIN(DECODE(row_num,1,value_id)) value_id1
,MIN(DECODE(row_num,2,variant_id)) variant_id2
,MIN(DECODE(row_num,2,value_id)) value_id2
,MIN(DECODE(row_num,3,variant_id)) variant_id3
,MIN(DECODE(row_num,3,value_id)) value_id3
,MIN(DECODE(row_num,4,variant_id)) variant_id4
,MIN(DECODE(row_num,4,value_id)) value_id4
,MIN(DECODE(row_num,5,variant_id)) variant_id5
,MIN(DECODE(row_num,5,value_id)) value_id5
,MIN(DECODE(row_num,6,variant_id)) variant_id6
,MIN(DECODE(row_num,6,value_id)) value_id6
FROM (SELECT item
,product_id
,row_number () OVER (PARTITION BY item ORDER BY variant_id) row_num
,variant_id
,value_id
FROM mffecom.item_variant)
GROUP BY item
,product_id) v_variant
,item_temp it
WHERE v_item.item = v_selling.item (+)
AND v_item.item = v_product.item (+)
AND v_item.item = v_variant.item (+)
AND v_item.item = it.item
AND v_item.supplier = NVL(:PM_supplier,v_item.supplier)
AND (v_product.prod_created_by = :PM_prod_created_by OR :PM_prod_created_by IS NULL)
AND (v_product.item_created_by = :PM_item_created_by OR :PM_item_created_by IS NULL)
AND (v_product.prod_created_date BETWEEN :prod_created_date_start AND :prod_created_date_to OR :prod_created_date_start IS NULL)
AND (v_product.item_created_date BETWEEN :item_created_date_start AND :item_created_date_to OR :item_created_date_start IS NULL)
ORDER BY v_product.product_id

Generating efficient LEFT JOIN with COUNT in Linq to Entities

I have this schema:
Lists ( ListId, Name, DateCreated, ... )
ListItems( ListId, Text, Foo, Baz, Qux, ... )
I have an IQueryable<List> which represents another Linq query which returns some List entities.
I want to JOIN it with some aggregate data of ListItems, but this proving difficult as Linq is generating inefficient SQL - but I also want to make the query composable.
Here is something similar to the SQL I want Linq to generate:
SELECT
*
FROM
(
-- This part represents the IQueryable:
SELECT
ListId,
Name,
...
FROM
Lists
ORDER BY
Lists.DateCreated
OFFSET
0 ROWS FETCH NEXT 25 ROWS ONLY -- Linq's .Skip(0).Take(25)
) AS ListsResult
LEFT JOIN
(
-- This is the aggregate data query I want Linq to generate:
SELECT
ListId,
COUNT(1) AS [Count],
COUNT( CASE WHEN Foo = 'bar' THEN 1 ELSE NULL END ) AS CountFooBar,
COUNT( CASE WHEN Baz > 5 THEN 1 ELSE NULL END ) AS CountBaz5
FROM
ListItems
WHERE
Qux IS NOT NULL
GROUP BY
ListId
) AS ItemsStats ON ListResults.ListId = ItemsStats.ListId
This is the Linq I have - I prefer the Extension Method syntax:
IQueryable lists = GetLists( 0, 25 );
var stats = this.dbContext.ListItems
.Where( (ListItem li) => li.Qux != null )
.GroupBy( (ListItem li) => li.ListId )
.Select( grp => new
{
grp.Key,
Count = grp.Count(),
CountFooBar = grp.Count( (ListItem li) => li.Foo == "bar" )
CountBaz5 = grp.Count( (ListItem li) => li.Baz > 5 )
} )
return lists
.Join(
inner: stats,
outerKeySelector: (List l) => l.ListId,
innerKeySelector: grp => grp.Key,
resultSelector: (list, itemStats) => new { list, itemsStats }
)
However this generates SQL looking like this (this query shows my real table and column names, which is a bit more complicated than the schema I posted earlier:)
SELECT
[Project13].[C2] AS [C1],
[Project13].[ListId] AS [ListId],
[Project13].[C1] AS [C2],
[Project13].[C3] AS [C3],
[Project13].[C4] AS [C4],
[Project13].[C5] AS [C5],
[Project13].[C6] AS [C6],
[Project13].[C7] AS [C7]
FROM ( SELECT
[Project11].[C1] AS [C1],
[Project11].[ListId] AS [ListId],
[Project11].[C2] AS [C2],
[Project11].[C3] AS [C3],
[Project11].[C4] AS [C4],
[Project11].[C5] AS [C5],
[Project11].[C6] AS [C6],
(SELECT
COUNT(1) AS [A1]
FROM (SELECT [Project12].[ListId] AS [ListId]
FROM ( SELECT
[Extent11].[ListId] AS [ListId],
[Extent11].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent11]
WHERE ([Extent11].[TenantId] = 8) AND ([Extent11].[BlarghId] = 8)
) AS [Project12]
ORDER BY [Project12].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit6]
INNER JOIN [dbo].[ListItems] AS [Extent12] ON ([Limit6].[TenantId] = [Extent12].[TenantId]) AND ([Limit6].[BlarghId] = [Extent12].[BlarghId]) AND ([Limit6].[ListId] = [Extent12].[ListId])
WHERE (([Extent12].[Baz] > 0) OR ((LEN([Extent12].[Notes])) > 0) OR ((LEN([Extent12].[Value])) > 0)) AND ([Project11].[TenantId] = [Extent12].[TenantId]) AND ([Project11].[BlarghId] = [Extent12].[BlarghId]) AND ([Project11].[ListId] = [Extent12].[ListId]) AND ([Extent12].[RecommendationRevision] IS NOT NULL)) AS [C7]
FROM ( SELECT
[Project9].[C1] AS [C1],
[Project9].[TenantId] AS [TenantId],
[Project9].[BlarghId] AS [BlarghId],
[Project9].[ListId] AS [ListId],
[Project9].[C2] AS [C2],
[Project9].[C3] AS [C3],
[Project9].[C4] AS [C4],
[Project9].[C5] AS [C5],
(SELECT
COUNT(1) AS [A1]
FROM (SELECT [Project10].[TenantId] AS [TenantId], [Project10].[BlarghId] AS [BlarghId], [Project10].[ListId] AS [ListId]
FROM ( SELECT
[Extent9].[TenantId] AS [TenantId],
[Extent9].[BlarghId] AS [BlarghId],
[Extent9].[ListId] AS [ListId],
[Extent9].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent9]
WHERE ([Extent9].[TenantId] = 8) AND ([Extent9].[BlarghId] = 8)
) AS [Project10]
ORDER BY [Project10].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit5]
INNER JOIN [dbo].[ListItems] AS [Extent10] ON ([Limit5].[TenantId] = [Extent10].[TenantId]) AND ([Limit5].[BlarghId] = [Extent10].[BlarghId]) AND ([Limit5].[ListId] = [Extent10].[ListId])
WHERE (([Extent10].[Baz] > 0) OR ((LEN([Extent10].[Notes])) > 0) OR ((LEN([Extent10].[Value])) > 0)) AND ([Project9].[TenantId] = [Extent10].[TenantId]) AND ([Project9].[BlarghId] = [Extent10].[BlarghId]) AND ([Project9].[ListId] = [Extent10].[ListId]) AND (3 = [Extent10].[Baz])) AS [C6]
FROM ( SELECT
[Project7].[C1] AS [C1],
[Project7].[TenantId] AS [TenantId],
[Project7].[BlarghId] AS [BlarghId],
[Project7].[ListId] AS [ListId],
[Project7].[C2] AS [C2],
[Project7].[C3] AS [C3],
[Project7].[C4] AS [C4],
(SELECT
COUNT(1) AS [A1]
FROM (SELECT [Project8].[TenantId] AS [TenantId], [Project8].[BlarghId] AS [BlarghId], [Project8].[ListId] AS [ListId]
FROM ( SELECT
[Extent7].[TenantId] AS [TenantId],
[Extent7].[BlarghId] AS [BlarghId],
[Extent7].[ListId] AS [ListId],
[Extent7].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent7]
WHERE ([Extent7].[TenantId] = 8) AND ([Extent7].[BlarghId] = 8)
) AS [Project8]
ORDER BY [Project8].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit4]
INNER JOIN [dbo].[ListItems] AS [Extent8] ON ([Limit4].[TenantId] = [Extent8].[TenantId]) AND ([Limit4].[BlarghId] = [Extent8].[BlarghId]) AND ([Limit4].[ListId] = [Extent8].[ListId])
WHERE (([Extent8].[Baz] > 0) OR ((LEN([Extent8].[Notes])) > 0) OR ((LEN([Extent8].[Value])) > 0)) AND ([Project7].[TenantId] = [Extent8].[TenantId]) AND ([Project7].[BlarghId] = [Extent8].[BlarghId]) AND ([Project7].[ListId] = [Extent8].[ListId]) AND (2 = [Extent8].[Baz])) AS [C5]
FROM ( SELECT
[Project5].[C1] AS [C1],
[Project5].[TenantId] AS [TenantId],
[Project5].[BlarghId] AS [BlarghId],
[Project5].[ListId] AS [ListId],
[Project5].[C2] AS [C2],
[Project5].[C3] AS [C3],
(SELECT
COUNT(1) AS [A1]
FROM (SELECT [Project6].[TenantId] AS [TenantId], [Project6].[BlarghId] AS [BlarghId], [Project6].[ListId] AS [ListId]
FROM ( SELECT
[Extent5].[TenantId] AS [TenantId],
[Extent5].[BlarghId] AS [BlarghId],
[Extent5].[ListId] AS [ListId],
[Extent5].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent5]
WHERE ([Extent5].[TenantId] = 8) AND ([Extent5].[BlarghId] = 8)
) AS [Project6]
ORDER BY [Project6].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit3]
INNER JOIN [dbo].[ListItems] AS [Extent6] ON ([Limit3].[TenantId] = [Extent6].[TenantId]) AND ([Limit3].[BlarghId] = [Extent6].[BlarghId]) AND ([Limit3].[ListId] = [Extent6].[ListId])
WHERE (([Extent6].[Baz] > 0) OR ((LEN([Extent6].[Notes])) > 0) OR ((LEN([Extent6].[Value])) > 0)) AND ([Project5].[TenantId] = [Extent6].[TenantId]) AND ([Project5].[BlarghId] = [Extent6].[BlarghId]) AND ([Project5].[ListId] = [Extent6].[ListId]) AND (1 = [Extent6].[Baz])) AS [C4]
FROM ( SELECT
[Project3].[C1] AS [C1],
[Project3].[TenantId] AS [TenantId],
[Project3].[BlarghId] AS [BlarghId],
[Project3].[ListId] AS [ListId],
[Project3].[C2] AS [C2],
(SELECT
COUNT(1) AS [A1]
FROM (SELECT [Project4].[TenantId] AS [TenantId], [Project4].[BlarghId] AS [BlarghId], [Project4].[ListId] AS [ListId]
FROM ( SELECT
[Extent3].[TenantId] AS [TenantId],
[Extent3].[BlarghId] AS [BlarghId],
[Extent3].[ListId] AS [ListId],
[Extent3].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent3]
WHERE ([Extent3].[TenantId] = 8) AND ([Extent3].[BlarghId] = 8)
) AS [Project4]
ORDER BY [Project4].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit2]
INNER JOIN [dbo].[ListItems] AS [Extent4] ON ([Limit2].[TenantId] = [Extent4].[TenantId]) AND ([Limit2].[BlarghId] = [Extent4].[BlarghId]) AND ([Limit2].[ListId] = [Extent4].[ListId])
WHERE (([Extent4].[Baz] > 0) OR ((LEN([Extent4].[Notes])) > 0) OR ((LEN([Extent4].[Value])) > 0)) AND ([Project3].[TenantId] = [Extent4].[TenantId]) AND ([Project3].[BlarghId] = [Extent4].[BlarghId]) AND ([Project3].[ListId] = [Extent4].[ListId]) AND ([Extent4].[Foo] = 1)) AS [C3]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [TenantId],
[GroupBy1].[K2] AS [BlarghId],
[GroupBy1].[K3] AS [ListId],
[GroupBy1].[K4] AS [C2]
FROM ( SELECT
[Project2].[K1] AS [K1],
[Project2].[K2] AS [K2],
[Project2].[K3] AS [K3],
[Project2].[K4] AS [K4],
COUNT([Project2].[A1]) AS [A1]
FROM ( SELECT
[Project2].[TenantId] AS [K1],
[Project2].[BlarghId] AS [K2],
[Project2].[ListId] AS [K3],
1 AS [K4],
1 AS [A1]
FROM ( SELECT
[Extent2].[ListId] AS [ListId]
FROM (SELECT [Project1].[ListId] AS [ListId]
FROM ( SELECT
[Extent1].[ListId] AS [ListId],
[Extent1].[Created] AS [Created]
FROM [dbo].[Lists] AS [Extent1]
WHERE ([Extent1].[TenantId] = 8) AND ([Extent1].[BlarghId] = 8)
) AS [Project1]
ORDER BY [Project1].[Created] DESC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit1]
INNER JOIN [dbo].[ListItems] AS [Extent2] ON (([Limit1].[ListId] = [Extent2].[ListId])
WHERE ([Extent2].[Baz] > 0) OR ((LEN([Extent2].[Notes])) > 0) OR ((LEN([Extent2].[Value])) > 0)
) AS [Project2]
) AS [Project2]
GROUP BY [K1], [K2], [K3], [K4]
) AS [GroupBy1]
) AS [Project3]
) AS [Project5]
) AS [Project7]
) AS [Project9]
) AS [Project11]
) AS [Project13]
It doesn't compose the COUNT() statements together at all, and it moves the COUNT predicates to separate WHERE clauses. Also note the repeated paged subqueries (where OFFSET 0 ROW FETCH NEXT 25 is used) whereas my hand-written query only executes it once.
Here's a semi-workaround I have:
I realised the best short-term solution is to have the SQL in the database (as a UDF FUNCTION or VIEW), this would mean that some data code would therefore have to be in the database (rather than using the DB as a "dumb store").
I first created a table-valued UDF which would accept a table-valued parameter, reasoning that would allow for composition, at the cost of needing to generate the input parameter table (an array of ListId values from the paged query). However in doing so, I realised that Linq-to-Entities (version 6) does not support table-valued parameters in Function Imports yet.
I then reasoned a better approach would be to move the COUNT operation to a VIEW (which represents one half of the LEFT JOIN I had in my hand-written query), and then I can get Linq to JOIN that against the existing IQueryable, thus retaining composability and generating an efficient runtime query (indeed, when I run it, the query takes 34ms to execute according to SQL Server Profiler, whereas the old Linq-generated inefficient query took 830ms).
Here's what I used:
CREATE VIEW ListItemStatistics AS
SELECT
ListId,
COUNT(*) AS [CountAll],
COUNT( CASE WHEN ... ) AS Count...
FROM
ListItems
WHERE
Foo = 'bar'
GROUP BY
ListId
And then from within Linq:
IQueryable lists = GetListsQuery( 0, 25 );
var listsWithItemsStats = lists.
.Join(
inner: this.dbContext.ListItemStatistics,
outerKeySelector: list => list.ListId,
innerKeySelector: row => row.ListId,
resultSelector: (list,row) => new { list, row }
);
However because this does use database-side logic (in the VIEW) it is not ideal.
In my experience EF generates such queries when you use aggregate functions that apply filtering like Count(predicate) in your case. You'll get much better SQL query if you replace Count(condition) construct with conditional sum (Sum(condition ? 1 : 0)) like this:
var stats = db.ListItems
.Where(li => li.Qux != null)
.GroupBy(li => li.ListId)
.Select(grp => new
{
grp.Key,
Count = grp.Count(),
CountFooBar = grp.Sum(li => li.Foo == "bar" ? 1 : 0),
CountBaz5 = grp.Sum(li => li.Baz > 5 ? 1 : 0)
});
The other parts stay the same. Before the mod I was getting similar SQL to the posted, and here is what I'm getting after this little mod:
SELECT
[Limit1].[ListId] AS [ListId],
[Limit1].[Name] AS [Name],
[Limit1].[DateCreated] AS [DateCreated],
[GroupBy1].[K1] AS [ListId1],
[GroupBy1].[A1] AS [C1],
[GroupBy1].[A2] AS [C2],
[GroupBy1].[A3] AS [C3]
FROM (SELECT [Extent1].[ListId] AS [ListId], [Extent1].[Name] AS [Name], [Extent1].[DateCreated] AS [DateCreated]
FROM [dbo].[List] AS [Extent1]
ORDER BY [Extent1].[DateCreated] ASC
OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY ) AS [Limit1]
INNER JOIN (SELECT
[Filter1].[K1] AS [K1],
COUNT([Filter1].[A1]) AS [A1],
SUM([Filter1].[A2]) AS [A2],
SUM([Filter1].[A3]) AS [A3]
FROM ( SELECT
[Extent2].[ListId] AS [K1],
1 AS [A1],
CASE WHEN (N'bar' = [Extent2].[Foo]) THEN 1 ELSE 0 END AS [A2],
CASE WHEN ([Extent2].[Baz] > 5) THEN 1 ELSE 0 END AS [A3]
FROM [dbo].[ListItem] AS [Extent2]
WHERE [Extent2].[Qux] IS NOT NULL
) AS [Filter1]
GROUP BY [K1] ) AS [GroupBy1] ON [Limit1].[ListId] = [GroupBy1].[K1]
UPDATE: The above is just the LINQ equivalent of your manual SQL query (when you adjust the join code to produce LEFT OUTER JOIN). However, taking into account the master data paging, OUTER APPLY SQL query might perform better. You can let LINQ to Entities generate such type of query like this:
var listsWithItemsStats = lists
.SelectMany(l => db.ListItems
.Where(li => li.ListId == l.ListId && li.Qux != null)
.GroupBy(li => li.ListId)
.Select(grp => new
{
grp.Key,
Count = grp.Count(),
CountFooBar = grp.Sum(li => li.Foo == "bar" ? 1 : 0),
CountBaz5 = grp.Sum(li => li.Baz > 5 ? 1 : 0)
})
.DefaultIfEmpty(),
(list, itemsStats) => new { list, itemsStats });

Tuning SQL Query in Oracle

I would really appreciate your help in tuning the below SQL query. It kept running for 10 mins when I cancelled it.
MARC_SEL gave me 31,253 records in 52 seconds
and MVKE_SEL gave me 431,060 records in 22 seconds
I refactored it to use with clause but nothing much changed.What else can I incorporate to make it faster. Please help.
WITH ALL_XSAP_MATNR
AS (SELECT DISTINCT XSAP.MATNR,XSAP.MTART,XSAP.SOURCE FROM XXX_MAIN.XXX_XSAP XSAP
WHERE SOURCE = 'SP' )
, MARC_SEL AS
( SELECT DISTINCT A.SOURCE
,MARA.MATNR
,MARA.MTART
,MARA.MBRSH
,MARC.WERKS
,NVL(PX.WERKS,'/') DWERK
,NVL(MBEW.HKMAT,'/') HKMAT
,NVL(MBEW.EKALR,'/') EKALR
,NVL(MARC.STAWN,'/') STAWN
FROM ALL_XSAP_MATNR A
, XXX_MAIN.XXX_SAP_MARA MARA
, XXX_MAIN.XXX_SAP_MARC MARC
, XXX_MAIN.XXX_MP_WERKS_PLANT_XREF PX
, XXX_MAIN.XXX_SAP_MBEW MBEW
WHERE A.MATNR = MARA.MATNR
AND A.MTART = MARA.MTART
AND MARA.MATNR = MARC.MATNR
AND MARC.MATNR = MBEW.MATNR
AND MARC.WERKS = MBEW.BWKEY
AND PX.LEGACY_PLANT = MARC.WERKS
AND PX.SOURCE = 'SP'
)
, MVKE_SEL AS
( SELECT DISTINCT
MVKE.MATNR
,'/' LEGACY_ORG
,'/' LEGACY_MATNR
,NVL(MX_VKORG.SAP_DE_VAL,'/') VKORG
,NVL(SUBSTR(MX_VKORG.SAP_DE,6,2),'/') VTWEG
-- ,NVL(TVRKME.MSEH3,'/') VRKME
,NVL(MVKE.KONDM,'/') KONDM
,NVL(MVKE.VERSG,'/') VERSG
,'/' IPRKZ
,'/' MHDRZ,NVL(MVKE.VMSTA,'/') VMSTA
,NVL(TO_CHAR(MVKE.VMSTD ,'YYYYMMDD' ),'/') VMSTD
,NVL(MVKE.PMATN,'/') PMATN
,NVL(MVKE.MVGR2,'/') MVGR2
,NVL(MVKE.MVGR3,'/') MVGR3
,NVL(MVKE.VAVME,'/') VAVME
,'/' MVGR4
,'/' MVGR5
,NVL(MVKE.MTPOS,'/') MTPOS
,NVL(MVKE.PRAT1,'/') PRAT1
,NVL(MVKE.SKTOF,'/') SKTOF
,'/' AUMNG
,NVL(MVKE.PRODH,'/') PRODH
,'/' MVGR1
,NVL(MVKE.KTGRM,'/') KTGRM
,MX_VKORG.DESC4
FROM XXX_MAIN.XXX_SAP_MVKE MVKE
, XXX_MAIN.XXX_MP_VKVT_XREF MX_VKORG
WHERE MX_VKORG.SOURCE_DE_VAL = MVKE.VKORG
AND SUBSTR(MX_VKORG.SAP_DE,6,2) = MVKE.VTWEG
AND MX_VKORG.SOURCE_TBL = 'SP'
AND MX_VKORG.SOURCE_DE = 'MVKE'
AND SUBSTR(MX_VKORG.SAP_DE,1,5)= 'VKORG'
AND MX_VKORG.DESC2 IS NULL )
SELECT DISTINCT
MARC.SOURCE
,MARC.MATNR
,MARC.MTART
,MARC.MBRSH
,MARC.WERKS
,MARC.DWERK
,MARC.HKMAT
,MARC.EKALR
,MARC.STAWN
,MVKE.LEGACY_ORG
,MVKE.LEGACY_MATNR
,MVKE.VKORG
,MVKE.VTWEG
,MVKE.KONDM
,MVKE.VERSG
,MVKE.VMSTA
,MVKE.VMSTD
,MVKE.PMATN
,MVKE.MVGR2
,MVKE.MVGR3
,MVKE.VAVME
,MVKE.MTPOS
,MVKE.PRAT1
,MVKE.SKTOF
,MVKE.PRODH
,MVKE.KTGRM
FROM MARC_SEL MARC
, MVKE_SEL MVKE
WHERE MARC.MATNR = MVKE.MATNR
AND MARC.WERKS = MVKE.DESC4
Start by simplifying your query as you do not need to do multiple DISTINCTs (it's only necessary in the final output) and you are selecting many columns that you are not outputting. You are also joining some tables which you are not selecting from and if there are multiple matching rows for these then it may generate duplicate rows - using something like EXISTS can eliminate these joins.
Like this:
WITH MARC_SEL AS (
SELECT A.SOURCE,
MARA.MATNR,
MARC.WERKS
FROM XXX_MAIN.XXX_XSAP A
INNER JOIN XXX_MAIN.XXX_SAP_MARA MARA
ON ( A.MATNR = MARA.MATNR
AND A.MTART = MARA.MTART )
INNER JOIN XXX_MAIN.XXX_SAP_MARC MARC
ON ( MARA.MATNR = MARC.MATNR )
WHERE EXISTS( SELECT 'X'
FROM XXX_MAIN.XXX_MP_WERKS_PLANT_XREF PX
WHERE PX.LEGACY_PLANT = MARC.WERKS
AND PX.SOURCE = 'SP' )
AND EXISTS( SELECT 'X'
FROM XXX_MAIN.XXX_SAP_MBEW MBEW
WHERE MARC.MATNR = MBEW.MATNR
AND MARC.WERKS = MBEW.BWKEY )
AND A.SOURCE = 'SP'
)
, MVKE_SEL AS (
SELECT NVL(MX_VKORG.SAP_DE_VAL,'/') VKORG,
NVL(SUBSTR(MX_VKORG.SAP_DE,6,2),'/') VTWEG,
MX_VKORG.DESC4
FROM XXX_MAIN.XXX_MP_VKVT_XREF MX_VKORG
WHERE EXISTS ( SELECT 'X'
FROM XXX_MAIN.XXX_SAP_MVKE MVKE
WHERE MX_VKORG.SOURCE_DE_VAL = MVKE.VKORG
AND SUBSTR(MX_VKORG.SAP_DE,6,2) = MVKE.VTWEG )
AND MX_VKORG.SOURCE_TBL = 'SP'
AND MX_VKORG.SOURCE_DE = 'MVKE'
AND SUBSTR(MX_VKORG.SAP_DE,1,5)= 'VKORG'
AND MX_VKORG.DESC2 IS NULL
)
SELECT DISTINCT
MARC.SOURCE,
MARC.MATNR,
MVKE.VKORG,
MARC.WERKS,
MVKE.VTWEG
FROM MARC_SEL MARC
INNER JOIN MVKE_SEL MVKE
ON ( MARC.MATNR = MVKE.MATNR
AND MARC.WERKS = MVKE.DESC4 )
Added hints to subqueries and it came back in a minute.
WITH ALL_XSAP_MATNR
AS (SELECT /*+ materialize */ DISTINCT XSAP.MATNR,XSAP.MTART,XSAP.SOURCE FROM XXX_MAIN.XXX_XSAP XSAP
WHERE SOURCE = 'SP' )
, MARC_SEL AS
( SELECT /*+ materialize */ DISTINCT A.SOURCE
,MARA.MATNR
,MARA.MTART
,MARA.MBRSH
,MARC.WERKS
,NVL(PX.WERKS,'/') DWERK
,NVL(MBEW.HKMAT,'/') HKMAT
,NVL(MBEW.EKALR,'/') EKALR
,NVL(MARC.STAWN,'/') STAWN
FROM ALL_XSAP_MATNR A
, XXX_MAIN.XXX_SAP_MARA MARA
, XXX_MAIN.XXX_SAP_MARC MARC
, XXX_MAIN.XXX_MP_WERKS_PLANT_XREF PX
, XXX_MAIN.XXX_SAP_MBEW MBEW
WHERE A.MATNR = MARA.MATNR
AND A.MTART = MARA.MTART
AND MARA.MATNR = MARC.MATNR
AND MARC.MATNR = MBEW.MATNR
AND MARC.WERKS = MBEW.BWKEY
AND PX.LEGACY_PLANT = MARC.WERKS
AND PX.SOURCE = 'SP'
)
, MVKE_SEL AS
( SELECT /*+ materialize */ DISTINCT
MVKE.MATNR
,'/' LEGACY_ORG
,'/' LEGACY_MATNR
,NVL(MX_VKORG.SAP_DE_VAL,'/') VKORG
,NVL(SUBSTR(MX_VKORG.SAP_DE,6,2),'/') VTWEG
-- ,NVL(TVRKME.MSEH3,'/') VRKME
,NVL(MVKE.KONDM,'/') KONDM
,NVL(MVKE.VERSG,'/') VERSG
,'/' IPRKZ
,'/' MHDRZ,NVL(MVKE.VMSTA,'/') VMSTA
,NVL(TO_CHAR(MVKE.VMSTD ,'YYYYMMDD' ),'/') VMSTD
,NVL(MVKE.PMATN,'/') PMATN
,NVL(MVKE.MVGR2,'/') MVGR2
,NVL(MVKE.MVGR3,'/') MVGR3
,NVL(MVKE.VAVME,'/') VAVME
,'/' MVGR4
,'/' MVGR5
,NVL(MVKE.MTPOS,'/') MTPOS
,NVL(MVKE.PRAT1,'/') PRAT1
,NVL(MVKE.SKTOF,'/') SKTOF
,'/' AUMNG
,NVL(MVKE.PRODH,'/') PRODH
,'/' MVGR1
,NVL(MVKE.KTGRM,'/') KTGRM
,MX_VKORG.DESC4
FROM XXX_MAIN.XXX_SAP_MVKE MVKE
, XXX_MAIN.XXX_MP_VKVT_XREF MX_VKORG
WHERE MX_VKORG.SOURCE_DE_VAL = MVKE.VKORG
AND SUBSTR(MX_VKORG.SAP_DE,6,2) = MVKE.VTWEG
AND MX_VKORG.SOURCE_TBL = 'SP'
AND MX_VKORG.SOURCE_DE = 'MVKE'
AND SUBSTR(MX_VKORG.SAP_DE,1,5)= 'VKORG'
AND MX_VKORG.DESC2 IS NULL )
SELECT DISTINCT /*+ use_hash(MARC,MVKE ) */
MARC.SOURCE
,MARC.MATNR
,MARC.MTART
,MARC.MBRSH
,MARC.WERKS
,MARC.DWERK
,MARC.HKMAT
,MARC.EKALR
,MARC.STAWN
,MVKE.LEGACY_ORG
,MVKE.LEGACY_MATNR
,MVKE.VKORG
,MVKE.VTWEG
,MVKE.KONDM
,MVKE.VERSG
,MVKE.VMSTA
,MVKE.VMSTD
,MVKE.PMATN
,MVKE.MVGR2
,MVKE.MVGR3
,MVKE.VAVME
,MVKE.MTPOS
,MVKE.PRAT1
,MVKE.SKTOF
,MVKE.PRODH
,MVKE.KTGRM
FROM MARC_SEL MARC
, MVKE_SEL MVKE
WHERE MARC.MATNR = MVKE.MATNR
AND MARC.WERKS = MVKE.DESC4

Outer join operator not allowed with OR in my WHERE clause - Error: ORA-01719

I need to check for the conditions at the bottom, but I cannot change use OR because of the (+) that are involved. I did not set that part up, so I am not sure how to rearrange it. Can someone tell me what I could do to get those conditions to go through?
SELECT DISTINCT
t.tkt_sid,
ts.tkt_sts_dsc,
tp.prty_dsc,
a.agt_cont_nbr,
au_a.user_nm assigned_to,
t.rcd_lst_user_ts
FROM
afp_asd.tkt t,
afp_asd.tkt_prty tp,
afp_asd.tkt_sts ts,
afp_asd.tkt_type tt,
afp_asd.tkt_log tl,
afp_asd.agt a,
afp_asd.asd_user au_a,
afp_asd.asd_user au_c,
afp_asd.asd_user au_l,
afp_asd.asd_user au_log,
afp_asd.prb_area pa1,
afp_asd.prb_area pa2,
afp_asd.prb_area pa3,
afp_asd.mktg_org mo,
afp_asd.src_sys ss,
afp_asd.agt ofc,
afp_asd.co c,
afp_asd.agt_sts ast
WHERE (
t.prty_cd = tp.prty_cd
AND t.tkt_sts_cd = ts.tkt_sts_cd
AND t.tkt_type_cd = tt.tkt_type_cd
AND t.agt_sid = a.agt_sid
AND t.assigned_id = au_a.asd_user_id
AND t.rcd_crt_user_id = au_c.asd_user_id (+)
AND t.lst_updater_id = au_l.asd_user_id
AND t.tkt_sid = tl.tkt_sid
AND t.prb_area_sid = pa3.prb_area_sid
AND tl.rcd_crt_user_id = au_log.asd_user_id
AND pa3.prb_hier_sid = pa2.prb_area_sid (+)
AND pa2.prb_hier_sid = pa1.prb_area_sid (+)
AND a.mktg_org_cd = mo.mktg_org_cd
AND a.src_sys_cd = mo.src_sys_cd
AND a.src_sys_cd = ss.src_sys_cd
AND a.ofc_id = ofc.agt_cont_nbr (+)
AND a.src_sys_cd = ofc.src_sys_cd (+)
AND a.co_sid = c.co_sid (+)
AND a.agt_sts_cd = ast.agt_sts_cd
AND tl.rcd_lst_user_ts >= :b_start_date
AND t.user_grp_sid = :b_group_id
)
AND (
(TKT_STS_DSC NOT LIKE 'Completed')
OR (
tp.prty_dsc = 'High'
AND ts.tkt_sts_dsc = 'Pending'
AND t.rcd_lst_user_ts < SYSDATE- 2
)
OR (
t.rcd_lst_user_ts < SYSDATE- 3
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'High'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 15
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'Medium'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 28
AND ts.tkt_sts_dsc = 'In Progress'
AND tp.prty_dsc = 'Low'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 7
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'High'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 21
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'Medium'
)
OR (
t.rcd_lst_user_ts < SYSDATE- 43
AND ts.tkt_sts_dsc = 'Pending'
AND tp.prty_dsc = 'Low'
)
)
ORDER BY ASSIGNED_TO,
PRTY_DSC
Don't use the old FROM TableA,TableB WHERE ... join syntax. Just don't.
Instead, write out your joins individually:
FROM TableA
INNER JOIN TableB ON ...
LEFT JOIN TableC ON ...
This isn't just a general rant against the old syntax: using the new (I say "new", but it's more than 20 years old now), standard syntax will fix your problem in this case.