Sql Server 2008 R2 Query Optimization - tsql

I have a Sql Ad-hoc query which is performing badly. Please help me or give me some suggestions to optimize it. Here is the query below:
SELECT TOP 20 CustomerPrimaryExtID,
Max(POSTimeStamp) AS TransactionDate,
ExtLocationCode,
0 AS RedemptionAmount,
0 AS RedemptionCount,
TerminalNum,
LogixTransNum,
POSTransNum AS TransNum,
0 AS DetailRecords,
CustomerTypeID,
PresentedCustomerID,
PresentedCardTypeID,
HHID,
Replayed,
0 AS TransContext,
isnull(TransTotal, 0) AS TransTotal
FROM TransHist AS TH WITH(nolock)
WHERE ( ( ( CustomerPrimaryExtID IN ( '' )
AND HHID IS NULL )
OR HHID = '0000000250000013408'
AND CustomerTypeID <> 1 )
OR ( CustomerPrimaryExtID = '0000000250000013408'
AND CustomerTypeID = 1 ) )
AND NOT EXISTS (SELECT LogixTransNum
FROM TransRedemptionView AS TR2
WHERE ( ( ( CustomerPrimaryExtID IN ( '' )
AND HHID IS NULL )
OR HHID = '0000000250000013408'
AND CustomerTypeID <> 1 )
OR ( CustomerPrimaryExtID = '0000000250000013408'
AND CustomerTypeID = 1 ) )
AND TH.LogixTransNum = TR2.LogixTransNum)
GROUP BY CustomerPrimaryExtID,
HHID,
CustomerTypeID,
PresentedCustomerID,
PresentedCardTypeID,
LogixTransNum,
POSTransNum,
TerminalNum,
ExtLocationCode,
Replayed,
TransTotal
ORDER BY TransactionDate DESC

Given the 62% cost on TransRedemption I would think an index on CustomerPrimaryExtID, HHID, CustomerTypeID and LogixTransNum would help that some.
You could also look at doing:
FROM
TransHist TH
LEFT OUTER JOIN
TransRedemption TR2
ON TH.LogixTransNum = TR2.LogixTransNum
Don't use the view in the sub query or the join unless something is being done in that view to limit the number of rows returned from TransRedemption.
Then remove:
AND NOT EXISTS (SELECT LogixTransNum
FROM TransRedemptionView AS TR2
WHERE ( ( ( CustomerPrimaryExtID IN ( '' )
AND HHID IS NULL )
OR HHID = '0000000250000013408'
AND CustomerTypeID <> 1 )
OR ( CustomerPrimaryExtID = '0000000250000013408'
AND CustomerTypeID = 1 ) )
AND TH.LogixTransNum = TR2.LogixTransNum)
from the where clause and replace with
AND TR2.LogixTransNum IS NULL
If TransRedemption has a lot of columns then you may want to limit the results in the join like so:
FROM
TransHist TH
LEFT OUTER JOIN
(
SELECT
LogixTransNum
FROM
TransRedemption
) TR2
ON TH.LogixTransNum = TR2.LogixTransNum

Related

insert with multiple subinserts - reference return value from previous subinsert in a following subinsert

I have a series of tables, each referencing the serial id from the preceding one. Is there a way to insert into all of them with a single statement? I have tried
WITH ins1 AS ( INSERT INTO tab1 ( col ) VALUES ( 'val' ) RETURNING tab1.id AS tab1id ),
ins2 AS ( INSERT INTO tab2 ( col ) VALUES ( tab1id ) RETURNING tab2.id AS tab2id )
INSERT INTO finaltab ( col ) VALUES ( tab2id );
but WITH clause values are only available in the final insert.
Trying
WITH ins2 AS (
INSERT INTO tab2 ( col )
SELECT tab1id FROM (
WITH ins1 AS (
INSERT INTO tab1 ( col )
VALUES ( 'val' )
RETURNING tab1.id AS tab1id
)
SELECT tab1id
)
RETURNING tab2.id AS tab2id
)
INSERT INTO finaltab ( col ) VALUES ( tab2id );
does not work because data-modifying WITH clauses must be top-level.
Is there a way to do this?
You need to select from the CTEs:
WITH ins1 AS (
INSERT INTO tab1 (col)
VALUES ('val')
RETURNING tab1.id AS tab1id
), ins2 AS (
INSERT INTO tab2 (col)
select tab1id
from ins1
RETURNING tab2.id AS tab2id
)
INSERT INTO finaltab (col)
select tab2id
from ins2;

creating self join which uses inner join , My requirement is delete same rows from it_med_t which are returned by the self join

Delete rows using self join.
Here is my query :
SELECT e1.I_NO FROM
it_med_t e1
INNER JOIN it_med_t e2 ON
e1.MED_REL_NO <> e2.MED_REL_NO
and (( e1.DEL_DATE is null and e2.DEL_DATE is not null) or ( e2.DEL_DATE is null and e1.DEL_DATE is not null))
AND e1.MED_NO = e2.MED_NO
AND e1.I_NO = e2.I_NO
where e1.DEL_DATE is not null);
I used ROWID, It solved my problem.
DELETE FROM it_med_t
WHERE ROWID IN (SELECT e1.ROWID
FROM it_med_t e1
inner join it_med_t e2
ON e1.med_rel_no <> e2.med_rel_no
AND ( ( e1.del_date IS NULL
AND e2.del_date IS NOT NULL )
OR ( e2.del_date IS NULL
AND e1.del_date IS NOT NULL ) )
AND e1.med_no = e2.med_no
AND e1.i_no = e2.i_no
WHERE e1.del_date IS NOT NULL);

SELECT Value even if NULL on LEFT JOIN

I am trying to pull data out and chuck it into a Stimulsoft report. The problem I am having is that I need it to output to two columns. I also need every "manager" record to show even if the count assigned to said record is NULL.
This is what i have at the moment:
DECLARE #ManagerCount INT = (( SELECT Count(*) FROM AM WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0 ) + 1) / 2
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
SELECT * FROM (
SELECT ta.id AS id1, ta.AMName AS ManagerName1, COUNT(*) AS ManagerCount1 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID BETWEEN 1 AND #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.ID, ta.AMName
) a
LEFT JOIN
(
SELECT ta.id AS id2,ta.AMName AS ManagerName2, COUNT(*) AS ManagerCount2 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID > #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.AMName, ta.ID
) b ON a.id1 + #ManagerCount = b.id2
Which ends up returning something like:
There are 18 managers so 9 per column, but this code doesn't show them all since anything that doesn't have a count in the first left join, won't show, and therefore the same row in column 2 doesn't show.
Results of SELECT * FROM #tmp_AM1:
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
SELECT * FROM (
SELECT ta.id AS id1, ta.AMName AS ManagerName1, COUNT(*) AS ManagerCount1 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID BETWEEN 1 AND #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.ID, ta.AMName
) a
LEFT OUTER JOIN
(
SELECT ta.id AS id2,ta.AMName AS ManagerName2, COUNT(*) AS ManagerCount2 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID > #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.AMName, ta.ID
) b ON a.id1 + #ManagerCount = b.id2 where ManagerName2 IS Null and ManagerCount2 IS NULL
just you want to use LEFT OUTER JOIN for select row even there is have any null values.,
Since the two subqueries are pretty much identical, except the where-statement, I would consiter rewriting it into one single query. I'm not sure why you need the same columns outputed into different columns in the result, but something like this might work:
WITH cte AS (
SELECT
ta.id AS id
,ta.AMName AS ManagerName
,COUNT(*) AS ManagerCount
,CASE WHEN ta.ID BETWEEN 1 AND #ManagerCount THEN 0 ELSE 1 END AS something
FROM
#tmp_AM1 tA
INNER JOIN Job J ON tA.AMID = j.AMID
WHERE
j.jobStatusID != 5
GROUP BY
ta.ID
,ta.AMName
,CASE WHEN ta.ID BETWEEN 1 AND #ManagerCount THEN 0 ELSE 1 END
)
SELECT
CASE WHEN something = 0 THEN cte.id ELSE null END AS id1
,CASE WHEN something = 0 THEN cte.ManagerName ELSE null END AS ManagerName1
,CASE WHEN something = 0 THEN cte.ManagerCount ELSE null END AS ManagerCount1
,CASE WHEN something = 1 THEN cte.id ELSE null END AS id2
,CASE WHEN something = 1 THEN cte.ManagerName ELSE null END AS ManagerName2
,CASE WHEN something = 1 THEN cte.ManagerCount ELSE null END AS ManagerCount2
FROM
cte
Probably not the best approach but i got the correct output using:
DECLARE #ManagerCount INT = (( SELECT Count(*) FROM AM WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0 ) + 1) / 2
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
ORDER By AMName
SELECT ManagerName1, ManagerName2, ManagerCount1, ManagerCount2 FROM (
SELECT AMID, ta.id AS id1, ta.AMName AS ManagerName1 FROM #tmp_AM1 tA
WHERE (ta.ID BETWEEN 1 AND #ManagerCount)
) a
LEFT JOIN
(
SELECT AMID, ISNULL(COUNT(*), 0) AS ManagerCount1 FROM Job j
INNER JOIN tblJobOutcome jO ON j.JobOutcomeID = jo.JobOutcomeID AND jO.JobOutcomeID != 5
GROUP BY AMID
) a1 ON a.AMID = a1.AMID
LEFT JOIN
(
SELECT AMID, ta.id AS id2, ta.AMName AS ManagerName2 FROM #tmp_AM1 tA
WHERE (ta.ID > #ManagerCount)
) b ON a.id1 + #ManagerCount = b.id2
LEFT JOIN
(
SELECT AMID, ISNULL(COUNT(*), 0) AS ManagerCount2 FROM Job j
INNER JOIN tblJobOutcome jO ON j.JobOutcomeID = jo.JobOutcomeID AND jO.JobOutcomeID != 5
GROUP BY AMID
) b1 ON b.AMID = b1.AMID
Gives me the correct output in two columns.
gives me this:

alternative way to TRIM for SSRS (not Crystal Reports)

I imported a report from Crystal to SSRS.
When I run the query in Microsoft Management Console, it throws errors unless I declare variables before the SELECT statement. When I run the query from Visual Studio, it bypasses these variables and only throws an error on the TRIM function.
From what I can tell a JOIN statement may be used instead of a TRIM, but I am not sure.
This is the portion of a where clause that I am trying to change/adapt to work with SSRS, which is throwing an error -- any suggestions appreciated.
Also, I am having issues with the DateSerial in the WHERE clause as follows:
AND (CAST(#StartDate AS Date) <> DateSerial(1900, 01, 01)) AND
Trim does not work in SQL only in the report expressions you would have to use LTrim and RTrim to make this work.
AND ( ( NOT ( #Status IS NULL )
AND RTrim(LTrim(#Status)) <> 'All' )
(( ( RTrim(Ltrim(#Status)) = 'Completed' )
AND RTrim(LTrim(#AssignedTo)) <> 'All' )
AND ( submission.assignedto IN ( #AssignedTo ) )
INCLUDING THE ENTIRE WHERE CLAUSE:
WHERE ( #ParameterIds IS NOT NULL or ParameterIds = #ParameterIds )
AND #ParameterIds <> 0 )
AND ( requested_table.parameterid IN ( #ParameterIds ) ) )
AND requested_table.columnname = 'INSERT'
AND ( ( NOT ( #Parameter2 IS NULL )
AND Trim(#Parameter2) <> 'All' )
AND (( ( Trim(#Parameter2) = 'Completed' )
AND (( requested_table.columnname = 'Dup'
OR requested_table.columnname = 'IDup'
OR requested_table.columnname = 'W/D'
OR requested_table.columnname = 'Done'
OR requested_table.columnname = 'QA Review Dup'
OR requested_table.columnname = 'X' ))
OR ( requested_table.columnname IN ( #Parameter2 ) ) )) )
AND ( ( #ParameterIds = 0 )
AND ( ( ( NOT ( #StartDate IS NULL )
AND ( Cast (#StartDate AS DATE) <>
Dateserial(1900, 01, 01) ) )
AND ( submission.dateimported >= Datevalue (#StartDate) ) )
AND ( ( NOT ( #EndDate IS NULL )
AND ( Cast (#EndDate AS DATE) <>
Dateserial(1900, 01, 01) )
)
AND ( table.dateimported <= Datevalue (#EndDate) )
) ) )
AND ( ( #ParameterIds = 0 )
AND (( ( NOT ( #Parameter5 IS NULL )
AND Trim(#Parameter5) <> 'All' )
AND ( table.assignedto IN ( #Parameter5 ) ) )) )
Fix the Dateserial and this should work.
WHERE ( #ParameterIds IS NOT NULL or ParameterIds = #ParameterIds )
AND (#ParameterIds <> 0 )
AND ( requested_table.parameterid IN ( #ParameterIds ) )
AND requested_table.columnname = 'INSERT'
AND ( ( (#Parameter2 IS NOT NULL )
AND LTRIM(RTrim(#Parameter2)) <> 'All' )
AND (( ( LTRIM(RTrim((#Parameter2)) = 'Completed' )
AND (( requested_table.columnname = 'Dup'
OR requested_table.columnname = 'IDup'
OR requested_table.columnname = 'W/D'
OR requested_table.columnname = 'Done'
OR requested_table.columnname = 'QA Review Dup'
OR requested_table.columnname = 'X' ))
OR ( requested_table.columnname IN ( #Parameter2 ) ) )) )
AND ( ( #ParameterIds = 0 )
AND ( ( ( ( #StartDate IS NOT NULL )
AND ( Cast (#StartDate AS DATE) <>
Dateserial(1900, 01, 01) ) )
AND ( submission.dateimported >= (#StartDate) ) )
AND ( ( ( #EndDate IS NOT NULL )
AND ( Cast (#EndDate AS DATE) <>
Dateserial(1900, 01, 01) )
)
AND ( table.dateimported <= (#EndDate) )
) ) )
AND ( ( #ParameterIds = 0 )
AND (( ( ( #Parameter5 IS NOT NULL )
AND RTRIM(LTrim(#Parameter5)) <> 'All' )
AND ( table.assignedto IN ( #Parameter5 ) ) )) )

TSQL dbo.split including a key

So I have the function below. My question is how can I get the following query to use the function to to create a view. I'm trying to get p_c_id to be the #ValueID and notes to be the #List.
select p_c_id, notes from dbo.product
create FUNCTION [dbo].[Split2Value]
( #Delimiter varchar(5),
#List varchar(8000),
#ValueID bigint
)
RETURNS #TableOfValues table
( RowID smallint IDENTITY(1,1),
[Value] varchar(500),
ValueID bigint
)
AS
BEGIN
DECLARE #LenString int
WHILE len( #List ) > 0
BEGIN
SELECT #LenString =
(CASE charindex( #Delimiter, #List )
WHEN 0 THEN len( #List )
ELSE ( charindex( #Delimiter, #List ) -1 )
END
)
INSERT INTO #TableOfValues
SELECT substring( #List, 1, #LenString ), #ValueID
SELECT #List =
(CASE ( len( #List ) - #LenString )
WHEN 0 THEN ''
ELSE right( #List, len( #List ) - #LenString - 1 )
END
)
END
RETURN
END
select
SV.RowID,
SV.[Value],
ValueID
from dbo.product as P
cross apply dbo.Split2Value('DELI?', P.notes, P.p_c_id) as SV