Need to set main.account = sub.account where main.id = sub.id - sql

This is my query, I need to write an update that will set mabi accountid = mb glinventory for each of the outputs that this select statement gives. This is what my select statement pulls
mabi.itemid
mabi.accountid
mb.glinventory
mb.itemid
758711763075273754
0
735174926379018147
758711763075273754
758711763074225163
0
735174926320297568
758711763074225163
758711763075273753
0
735174926379018147
758711763075273753
758711763074225169
0
735174926320297568
758711763074225169
758711763075273749
0
735174926320297568
758711763075273749
758711763074225162
0
735174926379018147
758711763074225162
Basically, I need to set the mabi accountid = mb glinventory for the rows in my output if that makes sense
SELECT
mabi.businessactionitemid,
mabi.accountid,
mb.glinventory,
mb.businessactionitemid
FROM
mabusinessactionitem mabi
INNER JOIN (
SELECT
mabi.accountid,
cat.glinventory,
mabi.businessactionitemid
FROM
cocategory cat
INNER JOIN mabusinessactionitem mabi ON cat.categoryid = mabi.categoryid
WHERE
cat.categoryid = mabi.categoryid
AND mabi.businessactionitemid IN (
SELECT
businessactionitemid
FROM
mabusinessactionitem mabi
INNER JOIN mabusinessaction maba ON maba.businessactionid = mabi.businessactionid
WHERE
documentnumber = '32103'
AND STATUS != 1
AND accountid = 0
)
) mb ON mb.businessactionitemid = mabi.businessactionitemid;
This is the select statement that pulls those outputs, I need to write an update to do what I described above. Im not sure of the best way to do it, I have tried
UPDATE mabi
SET mabi.accountid = mb.glinventory
FROM mabusinessactionitem mabi
JOIN (
SELECT mabi.accountid,
cat.glinventory,
mabi.businessactionitemid
FROM cocategory cat
INNER JOIN mabusinessactionitem mabi ON cat.categoryid = mabi.categoryid
WHERE cat.categoryid = mabi.categoryid
AND mabi.businessactionitemid IN (
SELECT businessactionitemid
FROM mabusinessactionitem mabi
INNER JOIN mabusinessaction maba ON maba.businessactionid = mabi.businessactionid
WHERE documentnumber = '32103'
AND STATUS != 1
AND accountid = 0
)
) mb ON mb.businessactionitemid = mabi.businessactionitemid;
I've done things similar, is this the right route, how would I complete this task. I effectively need to do
UPDATE mabi
SET mabi.accountid = mb.glinventory
WHERE mabi.itemid = mb.itemid

Your approach is actually correct. Just to combine it all together like this will do
UPDATE mabi
SET mabi.accountid = mb.glinventory
FROM mabi
JOIN mb
ON mabi.itemid = mb.itemid
If you need to check and filter by mabi.accountid, you can add a WHERE condition at the back. Like where mabi.accountid = 0

You are almost there, by the looks. You just need to join mabi and MB together:
UPDATE
mabi
SET
mabi.accountid = mb.glinventory
FROM
mabusinessactionitem mabi
INNER JOIN
(
SELECT
mabi.accountid,
cat.glinventory,
mabi.businessactionitemid
FROM
cocategory cat
INNER JOIN mabusinessactionitem mabi ON cat.categoryid = mabi.categoryid
WHERE
cat.categoryid = mabi.categoryid
AND mabi.businessactionitemid IN (
SELECT
businessactionitemid
FROM
mabusinessactionitem mabi
INNER JOIN mabusinessaction maba ON maba.businessactionid = mabi.businessactionid
WHERE
documentnumber = '32103'
AND STATUS != 1
AND accountid = 0
)
) mb ON mb.accountid = mabi.accountid;

Related

Where Clause Using Conditional Statement

i have query below
SELECT #RoleUser = MR.Code FROM MasterRole MR INNER JOIN MasterUsersRole MUR ON MR.Id = MUR.RoleId
INNER JOIN MasterUsers MU ON Mu.UserCode = MUR.UserCode
WHERE MU.UserCode = #UserLoginID
select 1 Num
, MyHistory.ID
, MyHistory.RequestNumber
, MyHistory.FlowID
, MyHistory.FlowProcessStatusID
from
(
select *
from Requests R
inner join
(
--DECLARE #UserLoginID nvarchar(200) = 'dum.testing.3'
select distinct
RequestID
from dbo.RequestTrackingHistory RTH
where IIF(#UserLoginID = 'admin', #UserLoginID, RTH.CreatedBy) = #UserLoginID
OR ( CreatedBy IN
SELECT Mu.UserCode from MasterUsers MU
INNER JOIN MasterUsersRole MUR ON MU.UserCode = MUR.UserCode
INNER JOIN MasterRole MR ON MUR.RoleId = MR.Id
WHERE MR.Code = #RoleUser
)
)
) RT on R.ID = RT.RequestID
) as MyHistory
inner join MasterFlow F on MyHistory.FlowID = F.ID
inner join
(
select FP.ID
, FP.Name
, FP.AssignType
, FP.AssignTo
, FP.IsStart
, case FP.AssignType
when 'GROUP' then
G.Name
end as 'AssignToName'
from MasterFlowProcess FP
left join dbo.MasterRole G on FP.AssignTo = G.ID and FP.AssignType = 'GROUP'
) FP on MyHistory.FlowProcessID = FP.ID
inner join MasterFlowProcessStatus FPS on MyHistory.FlowProcessStatusID = FPS.ID
left join MasterFlowProcessStatusNext FPSN on FPS.ID = FPSN.ProcessStatusFlowID
left join MasterFlowProcess FPN on FPSN.NextProcessFlowID = FPN.ID
left JOIN MasterRole MR ON MR.Id = FPN.AssignTo
left join MasterUsersRole MUR on MR.Id = MUR.RoleId
left join MasterUsers MURO on MUR.UserCode = MURO.UserCode
inner join MasterUsers UC on MyHistory.CreatedBy = UC.UserCode
left join MasterUsers UU on MyHistory.UpdatedBy = UU.UserCode
LEFT JOIN RequestMT RMT ON MyHistory.ID = RMT.RequestID
LEFT JOIN RequestGT RGT ON MyHistory.ID = RGT.RequestID
left join (SELECT sum(QtyCU) countQty , RequestId from dbo.RequestGTDetail where IsActive = 1 group by RequestId) RGTD on RGTD.RequestId = RGT.RequestId
left join (SELECT sum(QtyPCS) countQty , RequestId from dbo.RequestMTDetail where IsActive = 1 group by RequestId) RMTD on RMTD.RequestId = RMT.RequestId
left join (SELECT COUNT(IIF(returnable = 0, returnable, null)) countReturnable , RequestId from dbo.RequestMTDetail group by RequestId) RMTR on RMTR.RequestId = RMT.RequestId
left JOIN dbo.MasterDistributor md ON md.Code = RGT.CustId or md.Code = RMT.CustId
left JOIN dbo.MasterUsersDistributor MUD ON MUD.UserCode = MURO.UserCode AND md.Code = MUD.DistributorCode
LEFT JOIN dbo.MasterReason MRMT ON RMT.ReasonId = MRMT.Id
LEFT JOIN dbo.MasterReason MRGT ON RGT.ReasonId = MRGT.Id
LEFT JOIN dbo.MasterDistributorGroup MDG ON MDG.Id = MD.GroupId
OUTER APPLY dbo.FnGetHistoryApproveDate(MyHistory.Id) AS x
where REPLACE(FPS.Name, '#Requestor', uc.Name) <> 'DRAFT'
AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
i want to add some logic in where clause
this line
==> AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
it depend on the #RoleUser variable, if #RoleUser IN ('A','B') then where clause above is executed, but if #RoleUser Not IN ('A','B') where clause not executed
i,m trying this where clause
AND IIF(#RoleUser IN ('A','B'), MUD.DistributorCode, #RoleUser) IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = IIF(#RoleUser IN ('A','B'), #UserLoginID, NULL))
it didn't work, only executed if #RoleUser IS ('A','B') other than that it return 0 record
any help or advice is really appreciated
thank you
The cleanest way I'm implemented these kind of crazy rules is a
holderTable
and a countVariable against the holder table.
I'll give a generic examples.
This is a "approach" and "philosophy", not a specific answer....with complex WHERE clauses.
DECLARE #customerCountryCount int
DECLARE #customerCountry TABLE ( CountryName varchar(15) )
if ( "the moon is blue on tuesday" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Honduras" UNION ALL SELECT "Malaysia"
END
if ( "favorite color = green" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Greenland" UNION ALL SELECT "Peru"
END
SELECT #customerCountryCount = COUNT(*) FROM #customerCountry
Select * from dbo.Customers c
WHERE
(#customerCountryCount = 0)
OR
( exists (select null from #customerCountry innerVariableTable where UPPER(innerVariableTable.CountryName) = UPPER(c.Country) ))
)
This way, instead of putting all the "twisted logic" in an overly complex WHERE statement..... you have "separation of concerns"...
Your inserts into #customerCountry are separated from your use of #customerCountry.
And you have the #customerCountryCount "trick" to distinguish when nothing was used.
You can add a #customerCountryNotExists table as well, and code it to where not exists.
As a side note, you may want to try using a #temp table (instead of a #variabletable (#customerCountry above)... and performance test these 2 options.
There is no "single answer". You have to "try it out".
And many many variables go into #temp table performance (from a sql-server SETUP, not "how you code a stored procedure". That is way outside the scope of this question.
Here is a SOF link to "safe" #temp table usage.
Temporary table in SQL server causing ' There is already an object named' error

Else if in my select statement

I want to have an else if in my select statement i have already tried using case when but the results are not so accurate
heres a snippet of my scripts
select distinct t.MovementDate, t.ContractMovementID, t.GID,t.ReferenceGID,
p.refno, t.amount,convert(date,t.CreatedDate) as createdDat
from
LIF_MGM_T_Contract p
inner join LIF_MMS_T_PolicySuspense s with (nolock)
on s.ContractGID = p.GID
inner join LIF_TMS_T_FinancialTransaction t with (nolock)
on t.ContractGID = p.GID
where
p.refno = '1030642 - 1 - Mohahlaula'
and t.ReversedIndicator = 1
and t.counter = (select min(counter)
from LIF_TMS_T_FinancialTransaction t2 with (nolock)
where t2.ContractGID = p.GID
and t2.ReversedIndicator = 1
and t2.MovementDate = t.MovementDate )
So i want a else if t2.reversedindicator = 0 and date = getdate() return results.. Hope this makes sense

SQL Server - Variable assignment using UNION

I'm trying to assign a variable value using UNION ALL but i receive an error:
Variable assignment is not allowed in a statement containing a top
level UNION, INTERSECT or EXCEPT operator.
How can I assign a value using UNION? Here is the sql that i'm trying to make:
SELECT #Totals = SUM(Quantity)
FROM ConsData A WITH(NOLOCK)
INNER JOIN #TmpData B ON B.DataId = A.DataId
INNER JOIN Data cp ON cp.DataId = A.DataId
WHERE A.Status = -1 AND cp.Date IS NOT NULL
UNION ALL
SELECT #Totals = cg.Total
FROM ConsDataGenerated cg
INNER JOIN #TmpData B ON B.DataId = cg.DataId
INNER JOIN Data cp ON cp.DataId = B.DataId
WHERE cp.Date IS NULL
Try something like this....
DECLARE #Totals1 INT, #Totals2 INT, #GrandTotal INT;
SELECT #Totals1 = SUM(Quantity)
FROM ConsData A WITH(NOLOCK)
INNER JOIN #TmpData B ON B.DataId = A.DataId
INNER JOIN Data cp ON cp.DataId = A.DataId
WHERE A.Status = -1 AND cp.Date IS NOT NULL
SELECT #Totals2 = cg.Total --<-- Assuming this returns a Scalar value
FROM ConsDataGenerated cg
INNER JOIN #TmpData B ON B.DataId = cg.DataId
INNER JOIN Data cp ON cp.DataId = B.DataId
WHERE cp.Date IS NULL
SELECT #GrandTotal = ISNULL(#Totals1, 0) + ISNULL(#Totals2, 0);

Conditionally Join the Table with a Condition

I have 3 tables. BaseProducts, Products and ProductsMerchants. I need to find the count using a condition. This is my SQL,
ALTER PROCEDURE [dbo].[GetTotalProductsCount]
(
#SuperUser bit,
#MarchantId int
)
AS
BEGIN
IF(#SuperUser = 1)
BEGIN
SELECT COUNT(*) AS Total
FROM [dbo].[BaseProducts]
END
ELSE
BEGIN
SELECT COUNT(*) AS Total
FROM [dbo].[BaseProducts] BP
INNER JOIN [dbo].[Products] P ON P.BaseProductId = BP.Id
INNER JOIN ProductsMerchants PM ON PM.ProductId = P.Id
WHERE PM.MarchantId = #MarchantId;
END
END
The problem is that I need to rewrite the same query just for checking a condition. Can I make it one query?
You can do this:
SELECT COUNT(*) AS Total
FROM [dbo].[BaseProducts]
WHERE #SuperUser = 1
UNION ALL
SELECT COUNT(*) AS Total
FROM [dbo].[BaseProducts] BP
INNER JOIN [dbo].[Products] P ON P.BaseProductId = BP.Id
INNER JOIN ProductsMerchants PM ON PM.ProductId = P.Id
WHERE PM.MarchantId = #MarchantId AND #SuperUser <> 1;
Personally, I find the if form more understandable.
If the inner joins are being used for filtering and don't increase the number of rows, you could also do:
SELECT COUNT(*) AS Total
FROM [dbo].[BaseProducts] BP
LEFT JOIN [dbo].[Products] P ON P.BaseProductId = BP.Id
LEFT JOIN ProductsMerchants PM ON PM.ProductId = P.Id
WHERE PM.MarchantId = #MarchantId OR #SuperUser = 1;
(The PM.MarchantId = #MarchantId undoes the left outer join.)
But once again, I find that the intent of the if is clearer.
Or even this:
SELECT (CASE WHEN #SuperUser = 1 THEN CNT ELSE COUNT(*) END) AS Total
FROM (SELECT COUNT(*) as CNT FROM [dbo].[BaseProducts] BP) const CROSS JOIN
[dbo].[BaseProducts] BP
INNER JOIN [dbo].[Products] P ON P.BaseProductId = BP.Id
INNER JOIN ProductsMerchants PM ON PM.ProductId = P.Id
WHERE PM.MarchantId = #MarchantId OR #SuperUser = 1;

Query I need to be sped up

I have this query in SQL Server 2005:
SELECT J.JobID,
dbo.tblCustomers.Name AS CustomerName,
J.CustomerJobNumber,
J.JobName,
(CASE WHEN [tblCustomers].[CoreCust] = 0 THEN 'AUXILIARY' ELSE 'CORE' END) AS Department,
J.JobStatusID,
dbo.tblJobTypes.JobType
FROM dbo.tblJobs (NOLOCK) AS J
INNER JOIN dbo.tblCustomers (NOLOCK) ON J.CustomerID = dbo.tblCustomers.CustomerID
INNER JOIN dbo.tblJobTypes (NOLOCK) ON J.JobTypeID = dbo.tblJobTypes.JobTypeID
INNER JOIN dbo.tblDepartments (NOLOCK) ON J.DepartmentId = dbo.tblDepartments.DepartmentID
WHERE (J.Closed = 0)
AND (J.Invoiced = 0)
AND (J.Active = 1)
AND (dbo.fncIsAllPointsDelivered(J.JobID) = 1)
AND (J.DepartmentId <> 2)
This query is taking too long to run, and I know the problem is the UDF - (dbo.fncIsAllPointsDelivered(J.JobID) = 1) -.
The SQL for the UDF is here:
DECLARE #DetailCount int
DECLARE #TrackingCount int
SELECT #DetailCount = COUNT(*)
FROM [dbo].[tblLoadDetails] (NOLOCK)
WHERE JobId = #JobId
SELECT #TrackingCount = COUNT(*)
FROM [dbo].[tblLoadDetails] (NOLOCK)
WHERE JobId = #JobId AND Delivered = 1
IF(#DetailCount = #TrackingCount AND #DetailCount > 0)
RETURN 1
RETURN 0
All of this runs blazingly fast unless the job has a large number of load details in it. I am trying to think of a way to either make the UDF faster or get rid of the need for the UDF, but I am at a loss. I am hoping some of you SQL gurus will be able to help me.
SELECT *
FROM tblJobs j
INNER JOIN
tblCustomers c
ON c.CustomerID = J.CustomerID
INNER JOIN
tblJobTypes jt
ON jt.JobTypeID = J.JobTypeID
INNER JOIN
tblDepartments d
ON d.DepartmentID = J.DepartmentId
WHERE J.Closed = 0
AND J.Invoiced = 0
AND J.Active = 1
AND J.DepartmentId <> 2
AND J.JobID IN
(
SELECT JobID
FROM tblLoadDetails
)
AND J.JobID NOT IN
(
SELECT JobID
FROM tblLoadDetails
WHERE Delivered <> 1
)
Create a composite index on these fields:
tblJobs (Closed, Invoiced, Active) INCLUDE (DepartmentID)
If your tblLoadDetails.Delivered is a bit field, then create the following index:
tblLoadDetail (JobID, Delivered)
and rewrite the last condition as this:
SELECT *
FROM tblJobs j
INNER JOIN
tblCustomers c
ON c.CustomerID = J.CustomerID
INNER JOIN
tblJobTypes jt
ON jt.JobTypeID = J.JobTypeID
INNER JOIN
tblDepartments d
ON d.DepartmentID = J.DepartmentId
WHERE J.Closed = 0
AND J.Invoiced = 0
AND J.Active = 1
AND J.DepartmentId <> 2
AND
(
SELECT TOP 1 Delivered
FROM tblLoadDetails ld
WHERE ld.JobID = j.JobID
ORDER BY
Delivered
) = 1
I'm working this from the top of my head, so I haven't tried this out. But I think you could do this to remove the function. Replace the call to the function with these two clauses. This is assuming that 'Delivered' is a BIT field:
AND EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID)
AND NOT EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID AND Delivered = 0)
The AND EXISTS covers the UDF's #DetailCount > 0 check; the AND NOT EXISTS then covers the #DetailCount = #TrackingCount, the assumption I'm making is that you're looking to see if the job exists and everying to do with that job has been delivered. so if there's even one thing that hasn't been delivered, it needs to be excluded.
As mentioned: from top of head, and thus not tested or not profiled. I think I've got the logic right. If not, it should be a simple variation thereof.