How to Reduce Execution Time - sql

It's just my startup in SQL, I have 4.5 GB database from that I am trying to select records from specific dates and its 25 seconds execute. Is there a way to make it faster?
My query:
select a.*,b.ModelName
from Validation a
left Join ModelMaster b
on SUBSTRING(a.STB,11,2) = b.ProductCode and
Convert(int,substring(a.STB,9,2)) = b.BrandCode
Where STB in (Select STB From Scan_Data_For_Century) and
a.date between '2015-01-14' and '2015-01-14'

You can try query like this:
SELECT a.*,
b.ModelName
FROM Scan_Data_For_Century sd
INNER JOIN Validation a
ON a.STB = sd.STB AND a.date between '2015-01-14' and '2015-01-14'
LEFT JOIN ModelMaster b
ON SUBSTRING(a.STB,11,2) = b.ProductCode AND Convert(int,substring(a.STB,9,2)) = b.BrandCode
I know, that must be a comment. Please, try query. If it wont help I will remove my answer.

Try this:
;with cte as (
select
*,
ProductCode = SUBSTRING( STB, 11, 2 ),
BrandCode = Convert( int, substring( STB, 9, 2 ) )
from Validation
)
select
a.*,
c.ModelName
from
cte a
inner join Scan_Data_For_Century b on ( b.STB = a.STB )
left Join ModelMaster c on ( c.ProductCode = b.ProductCode ) and ( c.BrandCode = b.BrandCode )
Where
( a.date = '2015-01-14' )
Also indexes on:
Validation.STB
Validation.Date
Scan_Data_For_Century.STB
ModelMaster.ProductCode
ModelMaster.BrandCode
might be helpfull

Related

Get value from a joined table with no value in primary table

The query shown below is just about right, but I need to have a row for each fiscal Id, i.e. in the output shown below, there needs to be a new row after row 4 with data (screen shot below)
The query I'm using is:
SELECT a.companyId,a.profitCenterID,a.coaID,a.fiscalId,
COALESCE(SUM(a.amount * -1),0) amount,
twelveMo = (
SELECT COALESCE(SUM(amount * -1), 0)
FROM gl a1
LEFT OUTER JOIN fiscal f ON a1.fiscalId=f.Id
WHERE
a1.companyId = a.companyId AND
a1.profitCenterId = a.profitCenterId AND
a1.coaId = a.coaId AND
f.Id > a.fiscalId - 12 AND
f.Id <= a.fiscalId
)
FROM gl a
INNER JOIN coa c ON c.Id=a.coaId AND c.statementType=4
GROUP BY companyId,profitCenterId,coaId,a.fiscalId
ORDER BY companyId,profitCenterId,coaId,a.fiscalId
I don't know your sample datas and your schema's, so I've just added my query on the top of your's.
;WITH CTE_NUM_TEMP AS
(
SELECT 1 AS Fiscal
UNION ALL
SELECT Fiscal+1 FROM CTE_NUM_TEMP
WHERE Fiscal+1<=100
)
SELECT ISNULL(Der.companyId,1) AS companyId,ISNULL(Der.profitCenterID,1) AS profitCenterID,
ISNULL(Der.coaID,40000) AS coaID,IIF(twelveMo IS NULL,LAG(twelveMo,1) OVER(ORDER BY Fiscal),twelveMo) AS twelveMo
FROM CTE_NUM_TEMP AS Num
LEFT JOIN
(
SELECT a.companyId,a.profitCenterID,a.coaID,a.fiscalId,
COALESCE(SUM(a.amount * -1),0) amount,
twelveMo = (
SELECT COALESCE(SUM(amount * -1), 0)
FROM gl a1
LEFT OUTER JOIN fiscal f ON a1.fiscalId=f.Id
WHERE
a1.companyId = a.companyId AND
a1.profitCenterId = a.profitCenterId AND
a1.coaId = a.coaId AND
f.Id > a.fiscalId - 12 AND
f.Id <= a.fiscalId
)
FROM gl a
INNER JOIN coa c ON c.Id=a.coaId AND c.statementType=4
GROUP BY companyId,profitCenterId,coaId,a.fiscalId
)AS Der
ON Num.Fiscal=Der.fiscalId

Avoid SQL Pivot returning duplicate rows

I have the following SQL script which returns duplciate values in PIVOT. How do I combine those duplicate records to one row.
Please check the below image for the results set.
SELECT *
FROM (SELECT X.stockcode,
X.description,
X.pack,
X.location,
X.lname,
X.qty,
Y.stockcode AS StockCode2,
y.periodname,
Y.months,
Y.saleqty
FROM (SELECT dbo.stock_items.stockcode,
dbo.stock_items.description,
dbo.stock_items.pack,
dbo.stock_loc_info.location,
dbo.stock_locations.lname,
dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info
ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items
ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE ( dbo.stock_items.status = 's' )) AS X
LEFT OUTER JOIN (SELECT dbo.dr_invlines.stockcode,
( 12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate) ) % 12 + 1 AS Months,
Sum(dbo.dr_invlines.quantity) AS SaleQty,
dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status
ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines
ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode
ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno
WHERE ( STOCK_ITEMS_1.status = 'S' )
AND ( dbo.dr_trans.transtype IN ( 1, 2 ) )
AND ( dbo.dr_trans.transdate >= Dateadd(m, -6, Getdate()) )
GROUP BY dbo.dr_invlines.stockcode,
Datepart(month, dbo.dr_trans.transdate),
dbo.period_status.periodname) AS Y
ON X.stockcode = Y.stockcode) z
PIVOT (Sum(saleqty) FOR [months] IN ([1],[2],[3],[4],[5],[6])) AS pivoted
EDIT: I missed the root-cause of your issue being the inclusion of the periodname column causing the percieved duplication. I am leaving this in place as general solution showing CTE usage, because it could still be useful if you then want to do extra filtering/transformation of your pivot results
One way is to take the results of the pivot query and run it through a SELECT DISTINCT query.
An example of wrapping your pivot query as a CTE and using it to feed a SELECT DISTINCT below (please note: untested, but parses as valid in my SSMS)
WITH PivotResults_CTE (
stockcode,
description,
pack,
location,
lname,
qty,
StockCode2,
periodname,
months,
saleqty
)
AS (
SELECT *
FROM (
SELECT X.stockcode
,X.description
,X.pack
,X.location
,X.lname
,X.qty
,Y.stockcode AS StockCode2
,y.periodname
,Y.months
,Y.saleqty
FROM (
SELECT dbo.stock_items.stockcode
,dbo.stock_items.description
,dbo.stock_items.pack
,dbo.stock_loc_info.location
,dbo.stock_locations.lname
,dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE (dbo.stock_items.STATUS = 's')
) AS X
LEFT OUTER JOIN (
SELECT dbo.dr_invlines.stockcode
,(12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate)) % 12 + 1 AS Months
,Sum(dbo.dr_invlines.quantity) AS SaleQty
,dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno WHERE (STOCK_ITEMS_1.STATUS = 'S')
AND (
dbo.dr_trans.transtype IN (
1
,2
)
)
AND (dbo.dr_trans.transdate >= Dateadd(m, - 6, Getdate()))
GROUP BY dbo.dr_invlines.stockcode
,Datepart(month, dbo.dr_trans.transdate)
,dbo.period_status.periodname
) AS Y ON X.stockcode = Y.stockcode
) z
PIVOT(Sum(saleqty) FOR [months] IN (
[1]
,[2]
,[3]
,[4]
,[5]
,[6]
)) AS pivoted
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;
Also note, your sql included in the above may look slightly different to your original but that is only because i ran it through a reformatter to ensure i understood the structure of it.
In other words, the basic CTE wrapper for your pivot query is:
WITH PivotResults_CTE (
Field1,
Field2,
...
)
AS (
YOUR_PIVOT_QUERY_HERE
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;

not able to select a column outside left join

I am working with the below query
SELECT * FROM
(SELECT DISTINCT
a.Number
,a.Description
,ISNULL(temp.Quantity,0) Quantity
,LastReceived
,LastIssued
FROM Article a
LEFT JOIN (
select ss.ArticleId
, ss.Quantity
, max(lastreceiveddate) as LastReceived
, max(lastissueddate) as LastIssued
from StockSummary ss
where ss.UnitId = 8
group by ss.ArticleId, ss.StockQuantity
having (MAX(ss.LastReceivedDate) < '2014-09-01' or MAX(ss.LastReceivedDate) is NULL)
AND (MAX(ss.LastIssuedDate) < '2014-09-01' or MAX(ss.LastIssuedDate) is NULL)
) temp on a.Id = temp.ArticleId
WHERE a.UnitId = 8
) main
ORDER BY main.Number
What i want to achieve is to select the articles only with the MAX(ss.LastReceivedDate) and MAX(ss.LastIssuedDate) condition in the Left join query and then do the Quantity Select in the main query.
Note: the quantity column can be 0 or NULL.
Kindly help

Using CTE in a DELETE is not executing

Here is the original query that runs and runs:
;WITH includedCs_cte
AS
(
SELECT
x.PKey,
x.OKey,
y.CKey
FROM
#Permissions x
JOIN WHDATA.dbo.tb_DimC y
ON
x.PKey = y.PKey AND
x.OKey = y.OKey
)
, b_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCX b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, POK_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCY b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, includedOKeys
AS
(
SELECT *
FROM b_cte
UNION
SELECT * FROM POK_cte
)
DELETE FROM #Permissions
FROM #Permissions p
WHERE NOT EXISTS
(
SELECT 1
FROM includedOKeys x
WHERE
p.PKey = x.PKey AND
p.OKey = x.OKey
)
If I change the above to the below then it runs in less than 10 seconds. Why are these executing so differently?
;WITH includedCs_cte
AS
(
SELECT
x.PKey,
x.OKey,
y.CKey
FROM
#Permissions x
JOIN WHDATA.dbo.tb_DimC y
ON
x.PKey = y.PKey AND
x.OKey = y.OKey
)
, b_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCX b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, POK_cte
AS
(
SELECT
i.OKey,
i.PKey
FROM
WHData.dbo.vw_FactCY b
INNER JOIN includedCs_cte i
ON
b.PKey = i.PKey AND
b.PlayCKey = i.CKey
WHERE b.DateKey >= #myLAST28DAYS
GROUP BY
i.OKey,
i.PKey
)
, includedOKeys
AS
(
SELECT *
FROM b_cte
UNION
SELECT * FROM POK_cte
)
SELECT *
INTO #includedOKeys
FROM includedOKeys
CREATE CLUSTERED INDEX ix_inclProdOper ON #includedOKeys(OKey, PKey)
DELETE FROM #Permissions
FROM #Permissions p
WHERE NOT EXISTS
(
SELECT 1
FROM #includedOKeys x
WHERE
p.PKey = x.PKey AND
p.OKey = x.OKey
)
A CTE is resolved when it is used. It means that if you use it twice in a query, it may get resolved twice. CTEs do not always get resolved once and cache in memory. SQL Server is free to execute the query as it sees fit.
In your case, it may be worse than that - because you have used it as a correlated subquery in an EXISTS clause, which is a row-by-row operation. This probably means the plan results in the CTE being resolved for EACH ROW of the #permissions table! That could well be where all the time will be going. Show Execution Plan (Ctrl-L) in SSMS is your friend here.
Check this SQLFiddle, which shows that NONE of the GUIDs are the same, even though the CTE only creates 3 rows. In fact, we get 18 distinct GUIDs.
with cte(guid,other) as (
select newid(),1 union all
select newid(),2 union all
select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;

Sql Query to EF Linq Expression

Can anybody help with this sql Query to tranform it to EF Linq Expression?
SELECT Aitimata.id, AST.dateCr, AST.StatusId, Aitimata.UniqueCode, Aitimata.CategoryId, Aitimata.Thema
FROM Aitimata INNER JOIN
(select a.* from AitimataStatus a join
(select AitimaId, max(dateCr) AS dateCr
from AitimataStatus
group by AitimaId) b
on a.AitimaId = b.AitimaId and a.dateCr = b.dateCr)as AST ON Aitimata.id = AST.AitimaId
The important is this subquery
select a.* from AitimataStatus a join
(select AitimaId, max(dateCr) AS dateCr
from AitimataStatus
group by AitimaId) b
on a.AitimaId = b.AitimaId and a.dateCr = b.dateCr
you need extra info?
Thanks
It'll be something like this:
from a in AitimataStatus
let b = from as in AitimataStatus group by and other stuff and then select
join b on a.** equals b.**
Here is my solution
Dim sub1 = From aitst In context.AitimataStatus
Join aitst2 In (From aitst2 In context.AitimataStatus
Group aitst2 By cid = aitst2.AitimaId Into g = Group
Select New With {.AitimaId = cid, .dateCr = g.Max(Function(ddd) (ddd.dateCr))}
)
On aitst2.AitimaId Equals aitst.AitimaId And aitst2.dateCr Equals aitst.dateCr
Select aitst
it produce
SELECT
[Extent1].[id] AS [id],
[Extent1].[dateCr] AS [dateCr],
[Extent1].[UserId] AS [UserId],
[Extent1].[AitimaId] AS [AitimaId],
[Extent1].[StatusId] AS [StatusId]
FROM [dbo].[AitimataStatus] AS [Extent1]
INNER JOIN (SELECT
[Extent2].[AitimaId] AS [K1],
MAX([Extent2].[dateCr]) AS [A1]
FROM [dbo].[AitimataStatus] AS [Extent2]
GROUP BY [Extent2].[AitimaId] ) AS [GroupBy1] ON (([Extent1].[AitimaId] = [GroupBy1].[K1]) OR (([Extent1].[AitimaId] IS NULL) AND ([GroupBy1].[K1] IS NULL))) AND (([Extent1].[dateCr] = [GroupBy1].[A1]) OR (([Extent1].[dateCr] IS NULL) AND ([GroupBy1].[A1] IS NULL)))
.