SQL Server 2008 - Where Clause AND OR - sql-server-2008

(Read Only DB)I have the below Where Clause and it's slowing down my query. Is there a more efficeint way to write what I have below?
Also, how do I only pull back data only for 2016? with using the OR statement?
WHERE 1=1
AND b.Year(b.CreateDate) >= '2016'
AND B.ProcedureCode1 IN ('G0277','99183')
OR B.ProcedureCode2 IN ('G0277','99183')
OR B.ProcedureCode3 IN ('G0277','99183')
OR B.ProcedureCode4 IN ('G0277','99183')
OR B.ProcedureCode5 IN ('G0277','99183')
OR B.ProcedureCode6 IN ('G0277','99183')
OR B.ProcedureCode7 IN ('G0277','99183')
OR B.ProcedureCode8 IN ('G0277','99183')
OR B.ProcedureCode9 IN ('G0277','99183')
OR B.ProcedureCode10 IN ('G0277','99183')

If you can't change your schema to have many to many relationship with ProcedureCode table, you can try to create indexes on your ProcedureCodexx tables:
CREATE NONCLUSTERED INDEX IX_B_ProcedureCode1
ON B (ProcedureCode1)
GO
CREATE NONCLUSTERED INDEX IX_B_ProcedureCode2
ON B (ProcedureCode1)
GO

Related

What is the best solution for adding INDEX to speed up the query?

Now I have a Query that runs 50 minutes on Mysql database and I can't accept that...
I want this process can running under 15 minutes....
insert into appianData.IC_DeletedRecords
(sourcetableid,
concatkey,
sourcetablecode)
select mstid,
concatkey,
'icmstlocationheader' as sourcetablecode
from appianData.IC_MST_LocationHeader
where concatkey not in(select concatkey
from appianData.IC_PURGE_LocationHeader)
The "sourcetableid" and "mstid" are unique.
So what is the best way to add INDEX or optimize on this?
Thank you
I would write the select as:
select mstid, concatkey, 'icmstlocationheader' as sourcetablecode
from appianData.IC_MST_LocationHeader lh
where not exists (select 1
from appianData.IC_PURGE_LocationHeader lhp
where lhp.concatkey = lh.concatkey
);
Then you want an index on IC_PURGE_LocationHeader(concatkey).
Since it is a NOT IN condition you should be able to use a "LEFT JOIN ... WHERE rightTable has no match" without concern for multiple matches inflating the results.
INSERT INTO appianData.IC_DeletedRecords (sourcetableid, concatkey, sourcetablecode)
SELECT m.mstid, m.concatkey, 'icmstlocationheader' as sourcetablecode
FROM appianData.IC_MST_LocationHeader AS m
LEFT JOIN appianData.IC_PURGE_LocationHeader AS p
ON m.concatkey = p.concatkey
WHERE p.concatkey IS NULL
;
With this version query, or the one you presented in the question, indexes on concatkey in both source tables should help significantly.

Improving SQL Query Select Performance

I have a SQL query that pulls data from multiple tables. The only issue I am having is really the query takes to long and I was wondering if there is anyway I can speed it up. I made some minor improvements by using INNER JOIN rather than LEFT JOIN but the query is to slow.
SELECT
clientlist.CRMContactId,
clientlist.ClientAdviser,
COALESCE(NULLIF(clientlist.FirstName, ""), clientlist.CorporateName) AS FirstName,
clientlist.LastName,
clientlist.ServiceStatusName,
FORMAT(t.totalfum, 2) AS "Funds Under Management",
FORMAT(d.totalfci, 2) AS "Total Income",
(SELECT DueDate
FROM tasks
WHERE ClientRef = clientlist.ClientRef
AND `Status` <> "Complete"
ORDER BY DueDate DESC
LIMIT 1) AS NextDate,
(SELECT CompletedDate
FROM tasks
WHERE ClientRef = clientlist.ClientRef
AND `Status` = "Complete"
ORDER BY DueDate DESC
LIMIT 1) AS LastDate
FROM
clientlist
INNER JOIN
(SELECT
plans.ClientId, SUM(plans.CurrentVal) AS totalfum
FROM
plans
GROUP BY
plans.ClientId) t ON clientlist.CRMContactId = t.ClientId
INNER JOIN
(SELECT
adviserfci.ClientId, SUM(adviserfci.Payable) AS totalfci
FROM
adviserfci
WHERE
IncomeType IN ("Renewal Commission", "Ongoing Fee", "Fund Based Commission")
OR (Incometype = "Payaway Received"
AND UnderlyingIncomeType IN ("Renewal", "Ongoing Fee", "Fund Based"))
GROUP BY
adviserfci.ClientId) d ON clientlist.CRMContactId = d.ClientId
WHERE
d.totalfci IS NOT NULL
I've also read somewhere the explain command will help determine issues however I don't understand the response.
Is there any way I can increase the performance of this query?
Fold the test for d.totalfci IS NOT NULL into the subquery that generates it, even if it needs to be in a HAVING clause.
Add some indexes
tasks: INDEX(ClientRef, `Status`, DueDate)
plans: INDEX(ClientId, CurrentVal)
adviserfci: INDEX(ClientId)
First and foremost do you have indexes created for these tables?
Without knowing your data structured and what kind of query load you're going to be putting in them is hard to tell but on first look I'd say these indexes should improve performance, if you don't have them yet:
CRMContactId on table clientlist
ClientId on table plans
ClientId on adviserfci (include IncomeType and Payable)
If you haven't set up table primary keys yet and from the column names they sound like decent candidate keys, so if that works you can kill two birds with one stone.

Mysql - Add if condition in the Mysql Query or a where clause

I have written a join query in MySQL which works well and shows the result.
I am trying to write a MySQL query that shows 2 additional columns with some calculations
If isPercent=1 then
New Column1=price*currentPercent/100
New Column2=LineItemQuantity*price
I tried to write this query in PHP but since there are 100,000s records it is timing out.
Here is MySQL query and the results shown below
Select
wl.LineItems_LineItemID,
wl.LineItemQuantity,
pj.IsPercent,
pj.CurrentPercent,
pj.CurrentRate,
cb.Price
from
WorkOrderLineItems wl,
PayScaleLoaclJObCodes pj,
ClientBillingRates cb
where
wl.LineItems_LineItemID=pj.JobCodeID
AND wl.LineItems_LineItemID=cb.ClientBillingRates_ID
AND pj.PayScalesLocal_ID='33'
I would write the query this way:
SELECT
wl.LineItems_LineItemID,
wl.LineItemQuantity,
pj.IsPercent,
pj.CurrentPercent,
pj.CurrentRate,
cb.Price,
IF(pj.IsPercent=1, cb.Price*pj.CurrentPercent/100, NULL) AS `New Column 1`,
IF(pj.IsPercent=1, wl.LineItemQuantity*cb.Price, NULL) AS `New Column 2`
FROM
WorkOrderLineItems wl
JOIN PayScaleLoaclJObCodes pj ON wl.LineItems_LineItemID = pj.JobCodeID
JOIN ClientBillingRates cb ON wl.LineItems_LineItemID = cb.ClientBillingRates_ID
WHERE pj.PayScalesLocal_ID = '33'
As in the comments above, I encourage you to use JOIN syntax instead of relying on old-fashioned comma-style joins.
As for the query timing out, I would guess that you don't have the right indexes to support this query. If you want help with query optimization, you should run SHOW CREATE TABLE <tablename> for each table in your query, and post the output in your question.

SQL statement hanging up in MySQL database

I am needing some SQL help. I have a SELECT statement that references several tables and is hanging up in the MySQL database. I would like to know if there is a better way to write this statement so that it runs efficiently and does not hang up the DB? Any help/direction would be appreciated. Thanks.
Here is the code:
Select Max(b.BurID) As BurID
From My.AppTable a,
My.AddressTable c,
My.BurTable b
Where a.AppID = c.AppID
And c.AppID = b.AppID
And (a.Forename = 'Bugs'
And a.Surname = 'Bunny'
And a.DOB = '1936-01-16'
And c.PostcodeAnywhereBuildingNumber = '999'
And c.PostcodeAnywherePostcode = 'SK99 9Q9'
And c.isPrimary = 1
And b.ErrorInd <> 1
And DateDiff(CurDate(), a.ApplicationDate) <= 30)
There is NO mysql error in the log. Sorry.
Pro tip: use explicit JOINs rather than a comma-separated list of tables. It's easier to see the logic you're using to JOIN that way. Rewriting your query to do that gives us this.
select Max(b.BurID) As BurID
From My.AppTable AS a
JOIN My.AddressTable AS c ON a.AppID = c.AppID
JOIN My.BurTable AS b ON c.AppID = b.AppID
WHERE (a.Forename = 'Bugs'
And a.Surname = 'Bunny'
And a.DOB = '1936-01-16'
And c.PostcodeAnywhereBuildingNumber = '999'
And c.PostcodeAnywherePostcode = 'SK99 9Q9'
And c.isPrimary = 1
And b.ErrorInd <> 1
And DateDiff(CurDate(), a.ApplicationDate) <= 30)
Next pro tip: Don't use functions (like DateDiff()) in WHERE clauses, because they defeat using indexes to search. That means you should change the last line of your query to
AND a.ApplicationDate >= CurDate() - INTERVAL 30 DAY
This has the same logic as in your query, but it leaves a naked (and therefore index-searchable) column name in the search expression.
Next, we need to look at your columns to see how you are searching, and cook up appropriate indexes.
Let's start with AppTable. You're screening by specific values of Forename, Surname, and DOB. You're screening by a range of ApplicationDate values. Finally you need AppID to manage your join. So, this compound index should help. Its columns are in the correct order to use a range scan to satisfy your query, and contains the needed results.
CREATE INDEX search1 USING BTREE
ON AppTable
(Forename, Surname, DOB, ApplicationDate, AppID)
Next, we can look at your AddressTable. Similar logic applies. You'll enter this table via the JOINed AppID, and then screen by specific values of three columns. So, try this index
CREATE INDEX search2 USING BTREE
ON AddressTable
(AppID, PostcodeAnywherePostcode, PostcodeAnywhereBuildingNumber, isPrimary)
Finally, we're on to your BurTable. Use similar logic as the other two, and try this index.
CREATE INDEX search3 USING BTREE
ON BurTable
(AppID, ErrorInd, BurID)
This kind of index is called a compound covering index, and can vastly speed up the sort of summary query you have asked about.

Confusion about an Indexed View

I have the following indexed view:
ALTER View [CIC].[vwCoaterC473Heat] WITH SCHEMABINDING
AS
Select
id as ID,
DATEADD(ms, -DATEPART(ms, read_time), read_time) as ReadTime,
equipment_id as EquipmentID,
...
...
From dbo.td_coater_c473_heat
Where read_time >= Convert(dateTime,'1/1/2012',120)
CREATE UNIQUE CLUSTERED INDEX [IX_vwCoaterC473Heat_ReadTime_EquipmentID_ID]
ON [CIC].[vwCoaterC473Heat]
(
[ReadTime] ASC,
[EquipmentID] ASC,
[ID] ASC
)
GO
And I have the following query that references the indexed view:
Select
r.Coater,
r.ReadTime,
C473_left_A_actual_Temp,
C473_right_A_actual_Temp,
C473_left_B_actual_Temp,
C473_right_B_actual_Temp,
HD02A_Actual_Voltage,
HD02A_Actual_Current,
HD02B_Actual_Voltage,
HD02B_Actual_Current
From Cic.RandyTemp r
Inner Join Cic.vwCoaterC473Heat a
On a.EquipmentId = r.Coater And a.ReadTime = r.ReadTime
The query plan generated from this looks as follows:
I'm curious why SQL Server is bypassing the persisted data from the indexed view, and querying the underlying table the view is based on.
Are you using SQL Server Standard Edition? If so you need to use the WITH (NOEXPAND) hint. Please try this version and see if the indexed view is used. It might just be that the optimizer has decided that accessing the index in the base table is more efficient.
SELECT
r.Coater,
r.ReadTime,
C473_left_A_actual_Temp, -- why no alias prefixes from here down?
C473_right_A_actual_Temp,
C473_left_B_actual_Temp,
C473_right_B_actual_Temp,
HD02A_Actual_Voltage,
HD02A_Actual_Current,
HD02B_Actual_Voltage,
HD02B_Actual_Current
FROM Cic.RandyTemp AS r
INNER JOIN Cic.vwCoaterC473Heat AS a WITH (NOEXPAND)
ON a.EquipmentId = r.Coater
AND a.ReadTime = r.ReadTime;