SQL server update statement getting Null - sql

UPDATE Newchat
Set [Answered] = (Select b.[Answered]
From Table1 b
where Newchat.CHAT_ID = b.[Chat ID]
and Newchat.Chat_Date >= '2017-Feb-22' and Newchat.Chat_Date <= '2017-Feb-28');
Whenever I'm running this code all rows of [Answered] are getting Null except this dates.
Please suggest someway.
I also tried applying filter "Newchat.[Answered] is not null"
UPDATE Newchat
Set [Answered] = (Select b.[Answered]
From Table1 b
where Newchat.CHAT_ID = b.[Chat ID] and Newchat.[Answered] is not null
and Newchat.Chat_Date >= '2017-Feb-22' and Newchat.Chat_Date <= '2017-Feb-28');
This too doesn't work.

When there is no match, you get NULL. Presumably you really want:
UPDATE nc
Set [Answered] = b.[Answered]
From NewChat nc join
Table1 b
on nc.CHAT_ID = b.[Chat ID] and
nc.Chat_Date >= '2017-Feb-22' and nc.Chat_Date <= '2017-Feb-28';
This only updates the rows that match the conditions.

You have two queries going on here. The inner one (inside the brackets) is supplying the data for the outer one which is doing the update. Your problem is that the inner query is restricted by dates, so it only supplies values for those dates. But the outer query updates all rows - with NULL where there is no data from the inner query.
Keeping close to the way you have set out your query, moving the date restrictions outside the brackets should give you what you want - like this:
UPDATE Newchat
Set [Answered] = ( Select b.[Answered]
From Table1 b
where Newchat.CHAT_ID = b.[Chat ID] )
WHERE Newchat.Chat_Date >= '2017-Feb-22' and Newchat.Chat_Date <= '2017-Feb-28';

Try below UPDATE statement:
UPDATE Newchat SET [Answered] = b.[Answered]
From Table1 b
WHERE Newchat.CHAT_ID = b.[Chat ID] AND DATEDIFF(DAY,Newchat.Chat_Date,'2017-
02-22') <= 0 AND DATEDIFF(DAY,Newchat.Chat_Date,'2017-02-28') >= 0

Related

UPDATE statement with JOIN in SQL Server Not Working as Expected

I'm attempting to update the LAST_INSPECTION_FW field for all records in the VEHICLES_FW table with the last JOB_DATE_FW for records with the REASON_CODE_FW = 35. However, what's happening is that once the below code is executed, it's not taking into consideration the WHERE clause. This causes all of the records to update when it should just be updating those with the REASON_CODE_FW = 35.
Is there a way to restructure this code to get it working correctly? Please help, thanks!
UPDATE VEHICLES_FW
SET VEHICLES_FW.LAST_INSPECTION_FW = JOB_HEADERS_FW.FIELD2MAX
FROM VEHICLES_FW
INNER JOIN (SELECT VEHICLE_ID_FW, MAX(JOB_DATE_FW) AS FIELD2MAX
FROM JOB_HEADERS_FW
GROUP BY VEHICLE_ID_FW) AS JOB_HEADERS_FW
ON VEHICLES_FW.VEHICLE_ID_FW = JOB_HEADERS_FW.VEHICLE_ID_FW
INNER JOIN JOB_DETAILS_FW
ON JOB_NUMBER_FW = JOB_NUMBER_FW
WHERE REASON_CODE_FW = '35'
Common Table Expressions are your friend here. SQL Server's strange UPDATE ... FROM syntax is not. EG
with JOB_HEADERS_FW_BY_VEHICLE_ID as
(
SELECT VEHICLE_ID_FW, MAX(JOB_DATE_FW) AS FIELD2MAX
FROM JOB_HEADERS_FW
GROUP BY VEHICLE_ID_FW
), q as
(
Select VEHICLES_FW.LAST_INSPECTION_FW, JOB_HEADERS_FW_BY_VEHICLE_ID.FIELD2MAX NEW_LAST_INSPECTION_FW
FROM VEHICLES_FW
INNER JOIN JOB_HEADERS_FW_BY_VEHICLE_ID
ON VEHICLES_FW.VEHICLE_ID_FW = JOB_HEADERS_FW_BY_VEHICLE_ID.VEHICLE_ID_FW
INNER JOIN JOB_DETAILS_FW
ON JOB_NUMBER_FW = JOB_NUMBER_FW
WHERE REASON_CODE_FW = '35'
)
UPDATE q set LAST_INSPECTION_FW = NEW_LAST_INSPECTION_FW
I suspect this does what you want:
update v
set last_inspection_fw = (
select max(j.job_date_fw)
from job_headers_fw j
inner join job_details_fw jd on jd.job_number_fw = j.job_number_fw
where j.vehicle_id_fw = v.vehicle_id_fw and jd.reason_code_fw = 35
)
from vehicles_fw v

My UPDATE statement with WHERE EXISTS does not limit to the SELECT statement results

I have data in a temporary table and I am checking for duplicates in two other tables. I want to set a flag on the temp table (SET DupFlag = TRUE) for all duplicates found. My SELECT statement works perfectly, returning only the 48 duplicates that I entered to test with. But when I add UPDATE and WHERE EXISTS, every record in idTempImport2 is set to TRUE instead of just the 48 records returned from the SELECT statement. Is my syntax wrong? It looks like this:
UPDATE idTempImport2 as tmp2 SET DupFlag = TRUE
WHERE EXISTS
(SELECT * FROM idTempImport2 tmp2
LEFT JOIN (SELECT im.idDate, im.UserID, im.ActionID, im.IsHC, idn.Epic1, idn.Epic2
FROM idMain AS im
INNER JOIN idNotes AS idn ON im.aID = idn.MainID
WHERE idDate BETWEEN "2017-01-02" AND "2017-01-31") AS qry
ON qry.idDate = tmp2.idDate AND qry.UserID = tmp2.UserID AND qry.ActionID = tmp2.ActionID AND qry.Epic1 = clng(tmp2.Epic1) AND qry.Epic2 = clng(tmp2.Epic2)
WHERE qry.Epic1 <> NULL);
I think the ultimate issue is that you want a correlated subquery. As written, the subquery has no connection to the outer query, so it is likely that at least one row meets the condition. So, everything gets updated.
I think you intend:
UPDATE idTempImport2 as tmp2
SET DupFlag = TRUE
WHERE EXISTS (SELECT im.idDate, im.UserID, im.ActionID, im.IsHC, idn.Epic1, idn.Epic2
FROM idMain AS im INNER JOIN
idNotes AS idn
ON im.aID = idn.MainID
WHERE idDate BETWEEN "2017-01-02" AND "2017-01-31" AND
im.idDate = tmp2.idDate AND im.UserID = tmp2.UserID AND
im.ActionID = tmp2.ActionID AND
?.Epic1 = clng(tmp2.Epic1) AND ?.Epic2 = clng(tmp2.Epic2)
);

update with subquery

The code :
UPDATE tt_t_documents
SET t_Doc_header_ID = (SELECT
MIN(dh.Doc_header_ID)
FROM tt_t_documents td WITH (NOLOCK)
JOIN Doc_header dh WITH (NOLOCK)
ON dh.DH_doc_number = td.t_dh_doc_number
AND dh.DH_sub = 1
JOIN Pred_entry pe WITH (NOLOCK)
ON pe.Pred_entry_ID = dh.DH_pred_entry
JOIN Doc_type dt WITH (NOLOCK)
ON dty.Doc_type_ID = pe.PD_doc_type
AND dt.DT_mode = 5
HAVING COUNT(dh.Doc_header_ID) = 1);
I want to update my columns, but before that I also want to check if there is only one ID found.
The problem in this select is that I get more than one ID.
How can I write a query that updates each row and checks in the same query that there is only one id found?
I am guessing that you intend something like this:
update td
set t_Doc_header_ID = min_Doc_header_ID
from tt_t_documents td join
(select DH_doc_number, min(dh.Doc_header_ID) as min_Doc_header_ID
from Doc_header dh join
Pred_entry pe
on pe.Pred_entry_ID = dh.DH_pred_entry join
Doc_type dt
on dty.Doc_type_ID = pe.PD_doc_type and dt.DT_mode = 5
where dh.DH_doc_number = td.t_dh_doc_number and dh.DH_sub = 1
group by DH_doc_number
having count(dh.Doc_header_ID) = 1
) dh
on dh.DH_doc_number = td.t_dh_doc_number;
Using a join also means that you do not update the values where the condition does not match. If you use a left join, then the values will be updated to NULL (if that is your intention).
I'm not sure I believe you are getting more than one id back with that select given that you are doing a 'min' on it and have no group by. It should be only returning the lowest value for Doc_header_id.
To do what you are asking, first, you should have some way of joining to the tt_t_documents table in the update statement (eg. where td.id == tt_t_documents.id).
Second, you could re-write it to use the sub-query in the from. Something like:
update
tt_t_documents
set
t_Doc_header_ID = x.Doc_Header_id
from tt_t_documents join (
select td.id,
min(dh.Doc_header_ID)
from
tt_t_documents td
join Doc_header dh
on dh.DH_doc_number = td.t_dh_doc_number
and dh.DH_sub = 1
join Pred_entry pe
on pe.Pred_entry_ID = dh.DH_pred_entry
join Doc_type dt
on dty.Doc_type_ID = pe.PD_doc_type
and dt.DT_mode = 5
group by td.id
having
count(dh.Doc_header_ID) = 1
) x on tt_t_documents.id= x.id;
The syntax may not be perfect and I'm not sure how you want to find the doc_header_id but it would be something like this. The sub query would only return values with 1 doc_header_id). Not knowing the schema of your tables, this is as close as I can get.

Subquery returns more than one value

SELECT [Acc_DocumentNo],[Acc_DocumentDate],[Acc_DocumentType],[Acc_DocumentRef],[Acc_DocumentAmount],
[Acc_CustomerID],[Acc_DebtorGroupID],[Acc_DebtorBranchID],
(SELECT Acc_ManualReferenceNo
FROM Acc_CreditDocuments
WHERE Acc_DocumentNo IN
(SELECT Acc_DocumentRef FROM Acc_CreditDocuments
WHERE Acc_DocumentNo = #DocumentNo)) As [Acc_ManualReferenceNo],
[Acc_Status],[Acc_CreatedBy],[Acc_CreatedAt],[Acc_ModifiedBy],[Acc_ModifiedAt]
FROM Acc_CreditDocuments
WHERE Acc_DocumentNo = #DocumentNo AND
Acc_DocumentRef <> Acc_DocumentNo
In above query, subquery statement for selecting Acc_ManualReferenceNo returns more than one value if it has more than one DocumentNo.
Can I open db cursor to fetch and insert the values one by one? Or is there any other way to do it?
Any help will be much appreciated!
JOIN the table with itself instead, like this:
SELECT
a1.[Acc_DocumentNo],
a1.[Acc_DocumentDate],
a1.[Acc_DocumentType],
a1.[Acc_DocumentRef],
a1.[Acc_DocumentAmount],
a1.[Acc_CustomerID],
a1.[Acc_DebtorGroupID],
a1.[Acc_DebtorBranchID],
a2.Acc_ManualReferenceNo As [Acc_ManualReferenceNo] -- < --
...
FROM Acc_CreditDocuments AS a1
INNER JOIN Acc_CreditDocuments AS a2 ON a1.cc_DocumentRef = a2.Acc_DocumentNo
WHERE Acc_DocumentNo = #DocumentNo
AND a1.Acc_DocumentRef <> a1.Acc_DocumentNo

Sql in sql server with convert

I am trying to use convert in an where clause in the select statement. My query looks like this:
SELECT DISTINCT TOP 10 [SurveyResult].*
,[Ticket].[RefNumber]
FROM [SurveyResult]
LEFT JOIN [Ticket] ON [SurveyResult].[TicketID] = [Ticket].[TicketID]
JOIN [SurveyResponse] AS SurveyResponse1 ON [SurveyResult].[ResultID] = SurveyResponse1.[ResultID]
JOIN [QuestionAnswer] AS QuestionAnswer1 ON SurveyResponse1.[AnswerID] = QuestionAnswer1.[AnswerID]
JOIN [SurveyQuestion] AS SurveyQuestion1 ON QuestionAnswer1.[QuestionID] = SurveyQuestion1.[QuestionID]
WHERE SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CONVERT(INT, SurveyResponse1.[Response]) >= 1
AND CONVERT(INT, SurveyResponse1.[Response]) <= 5
The problem is that I get some errors when converting the values to integer in the where statement.
I know I have some rows that don't contain numbers in the Response column but I filter those so without the convert part in the where clause I get only numbers so it works like this:
SELECT TOP 1000 [ResponseID]
,[ResultID]
,[Response]
FROM [WFSupport].[dbo].[SurveyResponse]
JOIN QuestionAnswer ON SurveyResponse.AnswerID = QuestionAnswer.AnswerID
WHERE QuestionAnswer.QuestionID = 'C10BF42E-5D51-46BC-AD89-E57BA80EECFD'
And in the results I get numbers but once I add the convert part in the statement I I get an error that it can't convert some text to numbers.
Either do like Mark says or just have NULL values default to something numerical, this would give you a where statement like:
WHERE SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CONVERT(INT, ISNULL(SurveyResponse1.[Response],0)) BETWEEN 1 AND 5
The important part is the ISNULL() function and I also used BETWEEN to avoid duplicate converts.
Try:
SELECT DISTINCT TOP 10
[SurveyResult].*,
[Ticket].[RefNumber]
FROM
[SurveyResult]
LEFT JOIN [Ticket] ON [SurveyResult].[TicketID] = [Ticket].[TicketID]
JOIN [SurveyResponse] AS SurveyResponse1
ON [SurveyResult].[ResultID] = SurveyResponse1.[ResultID]
JOIN [QuestionAnswer] AS QuestionAnswer1
ON SurveyResponse1.[AnswerID] = QuestionAnswer1.[AnswerID]
JOIN [SurveyQuestion] AS SurveyQuestion1
ON QuestionAnswer1.[QuestionID] = SurveyQuestion1.[QuestionID]
where SurveyQuestion1.[SurveyID] = [SurveyResult].[SurveyID]
AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CASE SurveyQuestion1.[QuestionID]
WHEN 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
THEN Convert(int, SurveyResponse1.[Response])
ELSE 0
END BETWEEN 1 AND 5
(The AND SurveyQuestion1.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016' is retained in case the query is using an index on QuestionID - if not, it can be removed, as the same condition is implicit in the subsequent CASE condition.)
Try this one -
SELECT DISTINCT TOP 10 sr.*, t.[RefNumber]
FROM dbo.SurveyResult sr
JOIN dbo.SurveyResponse sr2 ON sr.[ResultID] = sr2.[ResultID]
JOIN dbo.QuestionAnswer sa ON sr2.[AnswerID] = sa.[AnswerID]
JOIN dbo.SurveyQuestion sq ON sa.[QuestionID] = sq.[QuestionID] AND sq.[SurveyID] = sr.[SurveyID]
LEFT JOIN dbo.Ticket t ON sr.[TicketID] = t.[TicketID]
WHERE sq.[QuestionID] = 'C86CB39A-8FE0-4FE8-B38F-17F1BE611016'
AND CAST(ISNULL(sr2.[Response], 0) AS INT) BETWEEN 1 AND 5