How to UPDATE a table on SQL Server with multiple Joins on the updated table? (FROM FROM JOIN) - sql

How to UPDATE a table on SQL Server with multiple Joins on the updated table?
In MySQL you can define a Alias for updated table, but how does it works with TSQL.
UPDATE recert.ou --#1-- In MSSQL/TSQL no alias allowed
SET parent_id = o2.ID
FROM recert.ou as O
JOIN recert.country C ON C.ID = O.country_id
JOIN recert.ou P ON O.parent_id = P.ID and p.country_id <> O.country_id
JOIN recert.ou o2 on o2.name = p.name and c.ID = o2.country_id
JOIN recert.country as c2 on c2.ID = o2.country_id
WHERE O.ID = o2.ID
-
RESULT: *The table 'o' is ambiguous.*

This works on Sql Fiddle.
UPDATE o
SET parent_id = o2.ID
FROM recert O
JOIN c C ON C.ID = O.country_id
JOIN recert P ON O.parent_id = P.ID and p.country_id <> O.country_id
JOIN recert o2 on o2.name = p.name and c.ID = o2.country_id
JOIN c c2 on c2.ID = o2.country_id
WHERE O.ID = o2.ID
I suppose the problem arose because you tried to re-alias an alias, but I'm not sure.

You can move everything into the WHERE clause:
UPDATE o --#1-- In MSSQL/TSQL no alias allowed
SET parent_id = o2.ID
FROM c, o, o o2, C c2
Where o.country_id = c.id and o.parent_id = p.id and p.country_id <> O.country_id and
o2.name = p.name and c.ID = o2.country_id and c2.ID = o2.country_id
This is not my favorite style of joins, but it should suffice for your purposes.
However, in TSQL, I would really do the following. Create a query that returns the new update value for each id. Then write a query with the following format:
with toupdate as (<the query>)
update o
set o.parent_id = toupdate.id
from toupdate
where o.id = toupdate.id

You just need to remove the alias name for o table
UPDATE o
SET parent_id = o2.ID
FROM o
JOIN c C ON C.ID = o.country_id
JOIN o P ON o.parent_id = P.ID and p.country_id <> o.country_id
JOIN o o2 on o2.name = p.name and c.ID = o2.country_id
JOIN c c2 on c2.ID = o2.country_id
WHERE o.ID = o2.ID

self joined update
update #table1 set column1= b.column2
from #table1 #table1, #table1 b where #table1.Id=b.Id

Related

Aggregating two rows, SQL

This is an example of what I'm working on
table
Forgive the picture, I couldn't figure out the table feature
This is my code
select o.id order_id, m.id, m.override_pay_amt
from orders o
left join movement_order mo
on o.id = mo.order_id
and mo.company_id = 'TMS'
left join movement m
on mo.movement_id = m.id
and m.company_id ='TMS'
where o.status != 'V' and o.company_id = 'TMS' and (o.id = '6008227' or o.id = '6000006')
order by o.id
I can't figure out how to combine order_id 6008227 in to one row.
I've tried:
select o.id order_id, m.id, sum(m.override_pay_amt) pay
from orders o
left join movement_order mo
on o.id = mo.order_id
and mo.company_id = 'TMS'
left join movement m
on mo.movement_id = m.id
and m.company_id ='TMS'
where o.status != 'V' and o.company_id = 'TMS' and (o.id = '6008227' or o.id = '6000006')
group by o.id
order by o.id
but when I do this, it makes me group by m.id and nothing changes in the table.
What am I missing?

Converting SQL to LINQ with left join and group by

I have done this query by SQL, and want to translate to LINQ
SELECT
ENT_DESC,
CAT_DESC,
PART_NUM,
PART_DESC,
GROUP_CONCAT(PART_OPTIONS.CODE, CHAR(13)) AS CODE,
PART_OPTIONS.PROMPT AS PROMPT,
PART_OPTIONS.DESCRIPTION AS DESCRIPTION,
PART_OPTIONS.PRICE AS PRICE,
ATTRIBUTE_DATA.NOTE,
ATTRIBUTE_DATA.DESCRIPTION AS ATTR_DESC
FROM ITEM_DATA
LEFT JOIN PART_OPTIONS ON ITEM_DATA.ID = PART_OPTIONS.PART_ID
LEFT JOIN ATTRIBUTE_DATA ON ITEM_DATA.ID = ATTRIBUTE_DATA.PART_ID
GROUP BY PART_OPTIONS.PART_ID
I know how to do this without GROUP_CONCAT,
from c in ITEM_DATA
join a in ATTRIBUTE_DATA on c.ID equals a.PART_ID into at
from a in at.DefaultIfEmpty()
join p in PART_OPTIONS on c.ID equals p.PART_ID into pa
from p in pa.DefaultIfEmpty()
select new {
ENT_DESC = c.ENT_DESC,
CAT_DESC = c.CAT_DESC,
PART_NUM = c.PART_NUM,
PART_DESC = c.PART_DESC,
CODE = p.CODE,
PROMPT = p.PROMPT,
DESCRIPTION = p.DESCRIPTION,
PRICE = p.PRICE,
NOTE = a.NOTE,
ATTR_DESC = a.DESCRIPTION,
}
and also I have done GROUP_CONCAT separately
from c in ITEM_DATA
join a in ATTRIBUTE_DATA on c.ID equals a.PART_ID into at
from a in at.DefaultIfEmpty()
join p in PART_OPTIONS on c.ID equals p.PART_ID into pa
from p in pa.DefaultIfEmpty()
group p by p.PART_ID into ps
select new {
CODE = ps.Select(g=>g.CODE),
}
but after that "c" and "a" are gone and i don"t know how to get access to ITEM_DATA and ATTRIBUTE_DATA tables.

Newbie - incorrect syntax error near the word where

SELECT
o.id, o.Name, o.StageName, o.[Type], o.Account__c, o.SalesPerson__c,
o2.AccountId__c,o2.Sales_Person__c, o2.InvoiceDate__c
FROM customers.dbo.sales as o
INNER JOIN customers.dbo.account as a on a.Id = o.AccountId
INNER JOIN
(
Select MAX(Id)Id, AccountId
FROM customers.dbo.order__c
WHERE Sales_Person__c <> NULL
) as o1
INNER JOIN Customers.dbo.Order__c as o2 on o2.Id = o1.Id
WHERE (o.SalesPerson__c = NULL)
AND (o.[Type] = 'Renewal')
AND (o.StageName NOT LIKE 'Closed%')
Not sure what I did wrong. I'm getting the following error:
Incorrect syntax near the keyword 'Where'
I'm trying to get the most recent Order for each account. Any help would be greatly appreciated.
Your issue is the <> NULL and the = NULL, you need to use IS NULL or IS NOT NULL. Depending on your RDBMS you also need a GROUP BY in your subquery with the MAX():
select o.id
, o.Name
, o.StageName
, o.[Type]
, o.Account__c
,o.SalesPerson__c
, o2.AccountId__c
, o2.Sales_Person__c
, o2.InvoiceDate__c
from customers.dbo.sales as o
Inner Join customers.dbo.account as a
on a.Id = o.AccountId
INNER JOIN
(
Select MAX(Id)Id, AccountId
from customers.dbo.order__c
where Sales_Person__c IS NOT NULL
GROUP BY AccountId -- depending on the RDBMS you need a GROUP BY
) o1
INNER JOIN Customers.dbo.Order__c o2
on o2.Id = o1.Id
Where (o.SalesPerson__c IS NULL)
and (o.[Type] = 'Renewal')
and (o.StageName NOT LIKE 'Closed%')
Your Inner Join called o1 doesn't join on anything. I'm not sure exactly what you are trying to do, but I think if you remove the inner join for o1, and instead have that as an exists in your where clause, it might work better. You also have to change your o2 join to join on o2.AccountId = a.Id, which I think is what you are trying to do.
select o.id
, o.Name
, o.StageName
, o.[Type]
, o.Account__c
, o.SalesPerson__c
, o2.AccountId__c
, o2.Sales_Person__c
, o2.InvoiceDate__c
from customers.dbo.sales as o
Inner Join customers.dbo.account as a
on a.Id = o.AccountId
INNER JOIN Customers.dbo.Order__c as o2
on o2.AccountId = a.Id
Where (o.SalesPerson__c is NULL)
and (o.[Type] = 'Renewal')
and (o.StageName NOT LIKE 'Closed%')
and exists(
Select MAX(Id) as id
from customers.dbo.order__c c
where c.Sales_Person__c is not NULL
and id = o2.id)

Conditional INNER JOIN in SQL Server

I have a rather complex query that pretty much mimics a test query I have below:
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
INNER JOIN Group G ON C.CustomerId = G.CustomerId --Join only when C.code = 1
INNER JOIN GroupDetail D ON G.GroupId = D.DetailId --Join only when C.code = 1
WHERE G.Active = 1 AND --Only when C.code = 1
D.code = '1' AND --Only when C.code = 1
C.Id = #customerId
I'd like to do INNER JOINs on Group G and GroupDetail D (and ofcourse not have them in the WHERE conditions based on the table column C.code = 1
I replaced the INNER JOINs with LEFT OUTER JOINs for both the join conditions, but the result set is not what was expected
How do I conditionally do the JOIN
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
LEFT OUTER JOIN Group G ON C.CustomerId = G.CustomerId
LEFT OUTER JOIN GroupDetail D ON G.GroupId = D.DetailId
WHERE ((G.Active = 1 AND C.code = 1) OR G.Active IS NULL) AND
((D.code = '1' AND C.code = 1) OR D.code IS NULL) AND
C.Id = #customerId
I'm guessing you didn't include the IS NULL checks before so you never got to see rows where C.code <> 1 ?
You should check for NULL on a field that will never be null. This is almost always 'id', but it's not clear that you have a G.id or a D.id.
I'm guessing what you want is just a tighter ON clause, and a compound condition.
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
-- the next two joins happen only when c.code=1
-- their columns will be null when there is no match.
LEFT JOIN Group G ON C.CustomerId = G.CustomerId AND C.Code = 1
LEFT JOIN GroupDetail D ON G.GroupId = D.DetailId AND C.Code = 1
WHERE C.Id = #customerId AND --always check this
-- this condition is true if code is null or code isn't 1,
((C.code IS NULL or C.code <> 1)
-- or (if the code is 1), it is true if g.active and d.code
OR (G.Active = 1 AND D.code = '1'))
This will do a semi-join only when code is 1.
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD
ON C.CustomerId = CD.CustomerId
INNER JOIN Address A
ON CD.DetailID = A.DetailID
WHERE
C.Id = #customerId AND
(c.code != 1 OR
EXISTS(
SELECT NULL
FROM Group G
JOIN GroupDetail D ON G.GroupId = D.DetailId
WHERE
C.CustomerId = G.CustomerId AND
G.Active = 1 AND
D.code = '1'
))

SQL use nested select in middle of inner join

Is it possible to use a select in the middle of joining...
I am trying to do the following:
FROM
tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN ((SELECT
,Min(n.date) as [MinDate]
from tblNotes n
Where n.test = 'test') te
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp)
INNER Join tblClient c ON o.ClientId = c.Id
Basically in the select in the middle of the query it is selecting only the notes with min date. The problem is I need to do this here because I need from tblOrders to be the first table.......
Suggestions?
The INNER JOIN failed because you have a leading comma here:
,Min(n.date) as [MinDate]
I think you are looking for something like this:
SELECT ...
FROM tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN (
SELECT id, Min(date) as [MinDate]
from tblNotes
Where test = 'test'
group by id
) te <-- not sure what JOIN clause to use here, please post schema
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp
INNER Join tblClient c ON o.ClientId = c.Id
You are missing an alias and join condition:
FROM
tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN ((SELECT Min(n.date) as [MinDate]
from tblNotes n
Where n.test = 'test') te
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp)
-- missing
AS z
ON <join conditions haere>
INNER Join tblClient c ON o.ClientId = c.Id
Yes, you can have a Select in a Join.