SQL optimazation - sql-server

I am working on a database where a total of 788 data is currently stored and continuously increasing with time.
My code is as follows:
SELECT DISTINCT R.remarks, R.payerId, R.payername, R.payeraddress, R.collectorName, R.serialno, OOI.phone_no, CR.cr_no, F.application_no, R.series, R.txndate, R.amount, T.toda_name, B.brand_name, M.motor_no, M.chassis_no,
M.plate_no, F.date_issue, M.year_model, M.body_color, OOI.ice_person_name, OOI.ice_person_address, OOI.ice_person_contact_no, M.motor_id, F.franchise_id, LEFT(R.remarks, 4) AS franchise_no, SUBSTRING(R.remarks,
CHARINDEX('|', R.remarks) + 1, LEN(R.remarks)) AS motor_noremarks
FROM etracs_tayabas.dbo.Receipt AS R INNER JOIN
etracs_tayabas.dbo.ReceiptItem AS RI ON RI.parentid = R.objid INNER JOIN
etracs_tayabas.dbo.IncomeAccount AS IA ON IA.objid = RI.acctid LEFT OUTER JOIN
dbo.vfTA_tblMotor AS M ON M.motor_no = SUBSTRING(R.remarks, CHARINDEX('|', R.remarks) + 1, LEN(R.remarks)) LEFT OUTER JOIN
dbo.vfTA_tblOperatorOtherInfo AS OOI ON OOI.operator_id = R.payerId LEFT OUTER JOIN
dbo.vfTA_tblCertificateOfRegistration AS CR ON CR.motor_id = M.motor_id LEFT OUTER JOIN
dbo.vfTA_tblFranchise AS F ON F.or_id = R.objid LEFT OUTER JOIN
dbo.vfTA_tblTODA AS T ON T.toda_id = M.toda_id LEFT OUTER JOIN
dbo.vfTA_tblReconciledTaxpayer AS RT ON RT.payer_id = R.payerId LEFT OUTER JOIN
dbo.vfTA_tblBrand AS B ON B.brand_id = M.brand_id
WHERE (IA.objid = 'FTFA00000242') AND (F.franchise_id IS NULL) AND (R.voidId IS NULL) AND (R.remarks IS NOT NULL) AND (RT.rtp_id IS NULL)
Everytime I run this code, it always takes me up to 10 minutes long or more to load up all the values. I tried to make a SQL View of this same code but when I run it, the error Execution Timeout always shows.
I want to know:
What is the best optimization method for views and stored procedure?
How can I lessen the time it takes for the data to load given that it has 788 data and increasing over time?
How to prevent a lot of execution timeout to happen in SQL or even in a program?
Some sites that help teaches SQL optimization.
I am trying to learn optimization right now because I noticed that when I make a query, it usually takes a lot of time to load up and sometimes producing the error 'Execution Timeout'
I am currently new with this. Thanks in advance.

I think using DISTINCT against such many columns cost a lot. Is that really necessary for your query?
I also wondered the following part.
LEFT OUTER JOIN dbo.vfTA_tblMotor AS M ON M.motor_no = SUBSTRING(R.remarks, CHARINDEX('|', R.remarks) + 1, LEN(R.remarks))
It means there's no way to use INDEX for this relationship. How about adding a column to table etracs_tayabas.dbo.Receipt where you store the substring result, and calculating it when a record is inserted/updated to the table. In this way, you can make INDEX for this relationship and can optimise that part of JOIN.

Related

SQL Server - JOIN ON conditional statement

I have a specific problem where the JOIN ON can be based on one of two statements:
LEFT JOIN acc_seminar.t_Seminar_Gebühr semg ON
CASE
WHEN #Bool = 1
THEN ss1.TNOrder = semg.SemG_TN OR (ss1.TNOrder > #MaxTN AND semg.SemG_TN = #MaxTN)
ELSE
semg.SemG_TN = 1
END
As you can see, if a variable has a value equal to 1 then it should left join on one statement or join on the other if the variable value is not equal to 1.
As far as Googling tells me, something like this is not possible in SQL because CASE returns a value, not a statement. How could I change this to make it logically work as shown above?
CASE is an expression in T-SQL; there is no Case Statement in the language.
What you need here is just "normal" Boolean Logic:
LEFT JOIN acc_seminar.t_Seminar_Gebühr semg ON (#Bool = 1
AND ss1.TNOrder = semg.SemG_TN
OR (ss1.TNOrder > #MaxTN AND semg.SemG_TN = #MaxTN))
OR (#Bool = AND semg.SemG_TN = 1)
Note that Joins like this can be bad for performance due to bad query plan caching. As a result using Dynamic SQL, or OPTION (RECOMPILE) can help avoid using the wrong cached plan, or recreating it each time (respectively). Personally, I prefer the dynamic approach.

Is there a way to compare more than one value of dataset against a single value of another dataset in left outer join(Flink)

I am trying to find out a way to check whether two values of a dataset can be checked against one value of another dataset using Flink Left Outer Join?
final DataSet<type> finalDataSet = dataSet1
.leftOuterJoin(dataSet2)
.where("value1")
.equalTo("value2")
.with(new FunctionNameToBeImplemented())
.name("StepName");
This works fine for a one to one check.
Can there be a way to do something similar:
final DataSet<type> finalDataSet = dataSet1
.leftOuterJoin(dataSet2)
.where(["value1","value2"]) // List of values
.contains("value2")
.with(new FunctionNameToBeImplemented())
.name("StepName");
I expect the output to check value1 and then value2 and if any (or both) matches, pass it to the function "FunctionNameToBeImplemented()" for further processing.
The outer join in Flink's DataSet API are strictly equality joins.
You can implement your use case with two separate joins and union the result. In order to avoid duplicates, on of the join functions should check if the other condition applies as well and only produce a result if it does not.
left -\
> JOIN(l.val1 == r.val2)[emit result] ---------------------\
right -/ \
> UNION
left -\ /
> JOIN(l.val2 == r.val2)[emit result if l.val1 != r.val2) -/
right -/

SQL empty result from Query

THe problem that I'm struggling with is when the following query has putted in that the result still be empty:
SELECT teacher.name, teacher.surname, assignment.code
FROM teacher
JOIN assignment
ON assignment.code = teacher.bsnt
WHERE assignment.working_on_assignment = FALSE
What did I wrong?
If no teachers have any matching assignment records then an empty result set would be expected with an inner join. You can try doing a left (outer) join, and move the WHERE condition to the ON clause.
SELECT
teacher.name,
teacher.surname,
COALESCE(assignment.code, 'NA') AS code
FROM teacher
LEFT JOIN assignment
ON assignment.code = teacher.bsnt AND
assignment.working_on_assignment = FALSE
If every teacher has an NA code then you will know that there are no matches.

Returning from a join the first result of one column based one a second column

I need some help to improve part of my query. The query is returning the correct data, I just need to exclude some extra information that I don't need.
I believe that one of the main parts that will change is:
JOIN TBL_DATA_TYPE_RO_BODY TB ON TB.FK_ID_TBL_FILE_NAMES=VMI.ID_TBL_FILE_NAMES
In this part, I have, for example, 2 FK_ID_TBL_FILE_NAMES, it will return 2 results from TBL_DATA_TYPE_RO_BODY.
The data that I have is (I excluded some extra columns):
If I have 2 or more equal MAG for the same field "ONLY_FIELD_NAME" I should return only the first one (I don't care about the others one). I believe that this is a simple case for Group by, but I am having trouble doing the group by on the join.
My ideas:
Use select top (i.e. here)
Use first valeu (i.e. here)
What I have (note the 2 last lines):
Freq|Mag|Phase|Date|ONLY_FILE_NAME
1608039|767|3234|37:00.0|RO_Mass_Load_4b
1608039|781|3371|44:00.0|RO_Mass_Load_4b
1608039|788|3138|37:00.0|RO_Mass_Load_4b
1608039|797|3326|44:00.0|RO_Mass_Load_4b
1608039|808|3117|37:00.0|RO_Mass_Load_4b
1608039|808|3269|44:00.0|RO_Mass_Load_4b
What I would like to have (note the last line):
Freq|Mag|Phase|Date|ONLY_FILE_NAME
1608039|767|3234|37:00.0|RO_Mass_Load_4b
1608039|781|3371|44:00.0|RO_Mass_Load_4b
1608039|788|3138|37:00.0|RO_Mass_Load_4b
1608039|797|3326|44:00.0|RO_Mass_Load_4b
1608039|808|3117|37:00.0|RO_Mass_Load_4b
Note that the mag field is coming from my JOIN.
Ideas? Any help?
In case you wanna see the whole code is:
SELECT TW.CURRENT_MEASUREMENT as Cycle_Current_Measurement,
TW.REF_MEASUREMENT as Cycle_Ref_Measurement,
CONVERT(REAL,TT.CURRENT_TEMP) as Cycle_Current_Temp,
CONVERT(REAL,TT.REF_TEMP) as Cycle_Ref_Temp,
TP.TYPE as Cycle_Type, TB.FREQUENCY as Freq,
TB.MAGNITUDE as Mag,
TB.PHASE as Phase,
VMI.TIME_FORMATTED as Date,
VMI.ID_TBL_FILE_NAMES as IdFileNames, VMI.ID_TBL_DATA_TYPE_RO_HEADER as IdHeader, VMI.*
FROM VW_MAIN_INFO VMI
JOIN TBL_DATA_TYPE_RO_BODY TB ON TB.FK_ID_TBL_FILE_NAMES=VMI.ID_TBL_FILE_NAMES
LEFT JOIN TBL_POINTS_AND_CYCLES TP ON VMI.ID_TBL_DATA_TYPE_RO_HEADER = TP.FK_ID_TBL_DATA_TYPE_RO_HEADER
LEFT JOIN TBL_POINTS_AND_MEASUREMENT TW ON VMI.ID_TBL_DATA_TYPE_RO_HEADER = TW.FK_ID_TBL_DATA_TYPE_RO_HEADER
LEFT JOIN TBL_POINTS_AND_TEMP TT ON VMI.ID_TBL_DATA_TYPE_RO_HEADER = TT.FK_ID_TBL_DATA_TYPE_RO_HEADER
Try something like this. the partition by is like a group by; it defines groups over which row_number will auto-increment an integer by 1. The order by tells row_number which rows should have a lower number. So in this example, the lowest date will have RID = 1. Then subquery it, and select only those rows which have RID = 1
select *
from (select RID = row_number() over (partition by tb.Magnitude order by vmi.time_formatted)
from ...<rest of your query>) a
where a.RID = 1

Picking out pairs from SQL Server

I am working on exercise 16 from SQL-EX.com
Find the pairs of PC models having identical speeds and RAM.
As a result, each resulting pair is shown only once, i.e. (i, j) but not (j, i).
Result set: model with higher number, model with lower number, speed, and RAM.
I used the following query
SELECT B.code, B.model AS BM, A.code, A.model, A.speed, A.ram
FROM PC A
JOIN PC B
ON A.speed = B.speed AND A.ram = B.ram
WHERE A.model <> B.model
ORDER BY B.model ASC
How do I retrieve only the pairs where BM is higher than model?
Instead of using <>, use <:
SELECT
a.model,
b.model,
a.speed,
a.ram
FROM PC a
INNER JOIN PC b
ON b.speed = a.speed
AND b.ram = a.ram
AND b.model < a.model
Change this line:
WHERE A.model <> B.model
To this:
WHERE A.model > B.model
You also need to select the correct columns, but getting that WHERE expression right was the hard part.

Resources