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.
Related
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.
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.
I know what this warning means, however in this case there are definitely no null values.
The result also appears to be correct, but the warning makes me curious (and concerned) since it means there's something in play that I don't understand.
The warning is:
Warning: Null value is eliminated by an aggregate or other SET operation.
Here's the statement:
UPDATE Contacts
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM (
SELECT dbo.Contacts.ID
FROM dbo.Contacts
LEFT OUTER JOIN dbo.Order_Batches ON dbo.Order_Batches.EnteredByContactID = dbo.Contacts.ID
GROUP BY dbo.Contacts.ID
HAVING (COUNT(dbo.Order_Batches.ID) > 0)
) i
WHERE i.ID = Contacts.ID
As you can see, this is an UPDATE statement where I needed to do some join logic, and the COUNT() statement must be the problem. But if I take that nested SELECT out and run it by itself, there are no nulls in the result:
ID
37
39
52
54
79
81
I assume there's something about how this nested select works that I don't understand. I've tried looking at execution plans and pulling this apart in various ways to reveal a null value or some other problem. I've tried making tweaks to the statement to try and get a null to appear - no luck.
So, to be clear, I would like to understand why this message occurs, but only when the query is nested inside an UPDATE statement's FROM clause.
Does not need aggregation if you are ensuring that there is at least an order by the contact to update this. Use EXISTS instead.
UPDATE c
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM Contacts c
WHERE exists (
(
SELECT 1 -- making sure there is at least an order
FROM Order_Batches o
where o.EnteredByContactID = c.ID
)
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
I recently started using SQL for work and don't have much experience of it so I'm sorry if this is a ridiculous question.
I'm looking for an entry that was originally listed as X but was then later changed to Y, I figure that a nested sub query is the way to go but the one I'm trying doesn't seem to use the nested bit.
Here is the code I'm trying
SELECT *
FROM [HOME].[dba].[ARCHIVE]
where FRIE like 'AR8%'
and RESULT = 'X'
and EXISTS(SELECT FRIE, RESULT
FROM [HOME].[dba].[ARCHIVE]
where RESULT = 'Y');
Everything as far as the EXISTS works but afterwards it just ignores the nested query
Your query doesn't have the same WHERE clause in the EXISTS portion. I think this will work for you:
SELECT *
FROM [HOME].[dba].[ARCHIVE]
WHERE FRIE like 'AR8%'
AND RESULT = 'X'
AMD EXISTS(SELECT TOP 1 1
FROM [HOME].[dba].[ARCHIVE]
where FRIE like 'AR8%' AND RESULT = 'Y');
I'd recommend using an INNER JOIN to a subquery rather than using an EXISTS statement. Something like this:
SELECT *
FROM [HOME].[dba].[ARCHIVE] a
INNER JOIN (SELECT FRIE
FROM [HOME].[dba].[ARCHIVE]
WHERE RESULT = 'Y') t1 ON a.FRIE = t1.FRIE
WHERE
FRIE like 'AR8%'
and RESULT = 'X'
That would return all rows from ARCHIVE where they there is a row with the same FRIE with a RESULT of X and a RESULT of Y.
Hopefully that helps.