SQL Error 1016 - Inner Joins - sql

I'm trying to add inner joins to old SQL code to make it run more efficiently. But when I added them and tried to execute I get this error:
1016, Line 12 Outer join operators cannot be specified in a query containing joined tables
Here's the query:
select a.s_purchase_order as order_id,
a.order_type,
a.nobackorder,
a.order_note,
a.note,
a.rqst_dlvry_date,
b.customer_name ,
c.store_name,
(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info,
d.supplier_account
from VW_CustomerOrder a, Customer b, Store c, eligible_supplier d
where a.customer = c.customer
and a.store = c.store
and a.customer = b.customer
and c.customer *= d.customer
and c.store *= d.store
and a.supplier *= d.supplier
and a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id
Any idea what's causing it? I'm guessing it has something to do with the isnull?

Did you try this? It replaces your commas between your tables with INNER JOIN and LEFT JOIN
select a.s_purchase_order as order_id,
a.order_type,
a.nobackorder,
a.order_note,
a.note,
a.rqst_dlvry_date,
b.customer_name ,
c.store_name,
(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info,
d.supplier_account
from VW_CustomerOrder a
INNER JOIN Customer b
ON a.customer = b.customer
INNER JOIN Store c
ON a.customer = c.customer
and a.store = c.store
LEFT JOIN eligible_supplier d
ON c.customer = d.customer
and c.store = d.store
and a.supplier = d.supplier
where a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id

If you left your "*=" join operators in the code after you converted it to ANSI syntax, that would explain your error. Use = for all equality tests when using ANSI syntax -- the type of your JOIN should be explicit in the JOIN declaration itself (INNER, LEFT, RIGHT, etc.)

Related

SQL Multiple Left Joins performance is bad

So, I have a rather simple query, which works, but very slow.
Is there a better way to optimize the query? Should I break out the LEFT JOINS on multiple columns? What about doing multiple runs and using Union ALL to join them together?
The tables have maybe 500,000 ROWS in them, and are indexed well.
Please help. Query takes forever to run
SELECT
ep.Id,
ep.DisplayName,
ep.EmailAddress,
COALESCE(
gs.DisplayNameMember + ' (' + gd.DisplayName + ')',
ea.DisplayName ,
ep.TrusteeUserAccountName,
ep.Trustee
) AS Trustee
FROM
dbo.ExchangePermissions ep WITH (NOLOCK)
LEFT JOIN dbo.GroupDetail gd WITH (NOLOCK) ON (ep.Trustee = gd.[Identity] OR ep.Trustee = gd.DisplayName OR ep.TrusteeUserAccountName = gd.SamAccountName)
LEFT JOIN dbo.GroupMemberShip gs WITH (NOLOCK) ON gd.name = gs.groupname
LEFT JOIN dbo.ExchangeAccount ea WITH (NOLOCK) ON (ep.Trustee = ea.[Identity] OR ep.Trustee = ea.DisplayName OR ep.TrusteeUserAccountName = ea.SamAccountName)
WHERE
ep.OTHERID= #MyParameter
The ORs in your LEFT JOINs are not helping performance at all. You should break them down into separate queries and UNION the results together. Working from Vykintas answer, we get the following:
SELECT
ep.Id,
ep.DisplayName,
ep.EmailAddress,
COALESCE(
gs.DisplayNameMember + ' (' + gd.DisplayName + ')',
ep.TrusteeUserAccountName,
ep.Trustee
) AS Trustee
FROM
dbo.ExchangePermissions ep WITH (NOLOCK)
LEFT JOIN dbo.GroupDetail gd WITH (NOLOCK) ON ep.Trustee = gd.[Identity]
LEFT JOIN dbo.GroupMemberShip gs WITH (NOLOCK) ON gd.name = gs.groupname
WHERE
ep.OTHERID= #MyParameter
UNION
SELECT
ep.Id,
ep.DisplayName,
ep.EmailAddress,
COALESCE(
gs.DisplayNameMember + ' (' + gd.DisplayName + ')',
ep.TrusteeUserAccountName,
ep.Trustee
) AS Trustee
FROM
dbo.ExchangePermissions ep WITH (NOLOCK)
LEFT JOIN dbo.GroupDetail gd WITH (NOLOCK) ON ep.Trustee = gd.DisplayName
LEFT JOIN dbo.GroupMemberShip gs WITH (NOLOCK) ON gd.name = gs.groupname
WHERE
ep.OTHERID= #MyParameter
UNION
SELECT
ep.Id,
ep.DisplayName,
ep.EmailAddress,
COALESCE(
gs.DisplayNameMember + ' (' + gd.DisplayName + ')',
ep.TrusteeUserAccountName,
ep.Trustee
) AS Trustee
FROM
dbo.ExchangePermissions ep WITH (NOLOCK)
LEFT JOIN dbo.GroupDetail gd WITH (NOLOCK) ON ep.TrusteeUserAccountName = gd.SamAccountName
LEFT JOIN dbo.GroupMemberShip gs WITH (NOLOCK) ON gd.name = gs.groupname
WHERE
ep.OTHERID= #MyParameter

How to combine these 2 SQL query results?

1st Query:
Select O.TrainDate, O.RailHead, O.Position as Pos,
O.Iso, C.CustomerName + ' (' + O.Customer + ')' as Customer,
P.ProductName + ' ('+O.Product +')' as Product,
O.Target, O.Docket, o.Gross, o.Tare ,o.Net, o.ConNote, o.Description
from IsoOrders O, Customer C, Product P
where o.Customer = c.Customer
and p.Product = o.Product
and o.Traindate >= '12-14-2016'
and o.Iso = '040'
2nd Query:
select top 1 isodeldocket, product from trans where container = '040'
order by despatchdatetime desc
The last query's result was to be added as the last 2 columns of the 1st query.
Solving the problem in your query
You can do it like this:
select
O.TrainDate, O.RailHead, O.Position as Pos, O.Iso,
C.CustomerName + ' (' + O.Customer + ')' as Customer,
P.ProductName + ' ('+ O.Product +')' as Product,
O.Target, O.Docket, O.Gross, O.Tare, O.Net, O.ConNote, O.Description,
-- Added these columns
T.isodeldocket,
T.product
from
IsoOrders O,
Customer C,
Product P,
-- Added this derived table
(select top 1 isodeldocket, product
from trans
where container = '040'
order by despatchdatetime desc) T
where O.Customer = C.Customer and P.Product = O.Product
and O.Traindate >= '12-14-2016'
and O.Iso = '040'
Improving the query by using ANSI JOIN syntax
While you're refactoring this query, why not move to ANSI JOIN, which greatly simplifies readability and clearly shows the intent / difference between (INNER) JOIN and CROSS JOIN:
select
O.TrainDate, O.RailHead, O.Position as Pos, O.Iso,
C.CustomerName + ' (' + O.Customer + ')' as Customer,
P.ProductName + ' ('+ O.Product +')' as Product,
O.Target, O.Docket, O.Gross, O.Tare, O.Net, O.ConNote, O.Description,
T.isodeldocket,
T.product
from IsoOrders O
join Customer C on O.Customer = C.Customer
join Product P on P.Product = O.Product
-- CROSS JOIN more explicitly reveals your intention than a comma-separated table list
cross join (
select top 1 isodeldocket, product
from trans
where container = '040'
order by despatchdatetime desc
) T
where O.Traindate >= '12-14-2016'
and O.Iso = '040'
Correlating the "outer" O.Iso with the "inner" trans.container value
From your comments, I take that you want to take this one step further and avoid duplicating the '040' "parameter". This can be done in SQL Server using APPLY:
select
O.TrainDate, O.RailHead, O.Position as Pos, O.Iso,
C.CustomerName + ' (' + O.Customer + ')' as Customer,
P.ProductName + ' ('+ O.Product +')' as Product,
O.Target, O.Docket, O.Gross, O.Tare, O.Net, O.ConNote, O.Description,
T.isodeldocket,
T.product
from IsoOrders O
join Customer C on O.Customer = C.Customer
join Product P on P.Product = O.Product
-- Use CROSS APPLY rather than CROSS JOIN
cross apply (
select top 1 isodeldocket, product
from trans
where container = O.Iso -- Now, you can access "outer" columns
order by despatchdatetime desc
) T
where O.Traindate >= '12-14-2016'
and O.Iso = '040'

Issue with Order By with FOR XML in T-sql (The ORDER BY clause is invalid in views, inline functions, derived tables)

select a.Hall, a.Title,
STUFF((SELECT ', ' + '[' + CONVERT(varchar(2),DATEPART(Hour, b.StartFilm))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.StartFilm))
+ ' ' + CONVERT(varchar(2),DATEPART(Hour, b.EndTime))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.EndTime))
+ ']'
FROM (select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
) b
Where a.Hall = b.Hall and a.Title = b.Title
FOR XML PATH('')),1,1,'') As ShowTime
from (select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
Order by a.StartFilmTime
) a
group by a.Hall, a.Title
I get the error:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
Help please! (I have used FOR XML?)
Although your query does use FOR XML (for the GROUP_CONCAT workaround), you are applying the order by outside of the derived table that uses FOR XML, hence the error.
Given that you aren't including start date directly in the final select (although you are composing it as part of the STUFF ShowTime column), you also can't ORDER BY StartFilm in the final GROUP BY either, as the column would otherwise need to be included in the GROUP BY or as an aggregated column.
What you can do is move the ORDER BY into the STUFF and then order by the derived column ShowTime (since your query only runs for one given day, and StartFilmTime is the first part of the STUFFED composed column).
At the same time, I would DRY up the repetition on the derived table with a CTE:
WITH cteFiltered AS
(select c.Name as Hall, b.Title,
Convert(time,a.StartFilmTime) as StartFilm,
Convert(time,a.EndFilmTime) as EndTime
from FilmSchedule a
left join Film b on a.FilmId = b.Id
left join Room c on a.RoomId = c.Id
where a.ApproveStatus = 1 and a.Status = 1
and CONVERT(date, a.StartFilmTime) = '05-06-2015'
)
select
a.Hall,
a.Title,
STUFF((SELECT ', ' + '[' + CONVERT(varchar(2),DATEPART(Hour, b.StartFilm))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.StartFilm))
+ ' ' + CONVERT(varchar(2),DATEPART(Hour, b.EndTime))
+ ':' + CONVERT(varchar(2),DATEPART(Minute, b.EndTime))
+ ']'
FROM
cteFiltered b
Where
a.Hall = b.Hall and a.Title = b.Title
order by b.StartFilm -- ***
FOR XML PATH('')),1,1,'') As ShowTime
from
cteFiltered a
group by a.Hall, a.Title
order by ShowTime; -- *** Hour is first (assuming 24H format) and only one day

Stored procedure for a select statement

I got a select statement. I want to add a join to this select statement and the join which I want to add is at the bottom of this code. why am I unable to add one more left outer join for this select statement? The join which I want to add is at the bottom. I also need to write a stored procedure for the entire select statement:
SELECT
FactId, UserType,
wr.WorkRequestId, wr.XerisUserKey,
xu.CsuserUserID UserId,
u.fname UserFName, u.lname UserLName,
b.PatientId, p.firstname PatFName, p.lastname PatLName,
GroupId, HospiceGroupKey GroupKey, WR.ContactKey,
C.ContactId, C.FirstName, C.LastName,
Convert(datetime, (Convert(varchar, SD.Date, 101) + ' ' + ST.TimeOfDay )) Start_dtm,
Convert(datetime, (Convert(varchar, CD.Date, 101) + ' ' + CT.TimeOfDay )) End_dtm,
DATEDIFF(s,Convert(datetime,(Convert(varchar, SD.Date, 101) + ' ' + ST.TimeOfDay)),
Convert(datetime, (Convert(varchar, CD.Date, 101) + ' ' + CT.TimeOfDay ))) WRDuration,
(Convert(Decimal(18, 3), DATEDIFF(s, Convert(datetime,(Convert(varchar, SD.Date, 101) + ' ' + ST.TimeOfDay )),
Convert(datetime, (Convert(varchar, CD.Date, 101) + ' ' + CT.TimeOfDay ))))) *
(Convert(Decimal(18,3),LineItemCount)/Convert(Decimal(18,3),PatientBucketItemCount)) Duration,
CallBackNumber, WorkRequestType,
B.LineItemCount, ArchiveLocation, Processed,
ArchiveQueueType, TQA, Exclude, CallId
FROM
bi.dbo.FactWorkRequestTouches (NOlock) WR
INNER JOIN
bi.dbo.BridgePatientWorkRequest B ON B.WorkRequestId = WR.WorkRequestId
INNER JOIN
bi.dbo.dimPatient (NOlock) P ON B.PatientId = P.CphPatientID
INNER JOIN
bi.dbo.DimXerisUsers (NOlock) XU ON WR.XerisUserKey = XU.XerisUserKey
INNER JOIN
cdc.dbo.csuser (NOlock) U ON XU.CsuserUserID = u.user_id
INNER JOIN
bi.dbo.DimTimeOfDay (NOlock) ST ON WR.StartTimeOfDayKey = ST.TimeKey
INNER JOIN
bi.dbo.DimTimeOfDay (NOlock) CT ON WR.CompletedTimeOfDayKey = CT.TimeKey
INNER JOIN
bi.dbo.DimDate (NOlock) SD ON WR.StartDateKey = SD.DateKey
INNER JOIN
bi.dbo.DimDate (NOlock) CD ON WR.CompletedDateKey = CD.DateKey
LEFT OUTER JOIN
bi.dbo.DimContact (Nolock) C ON WR.ContactKey = C.ContactKey
WHERE
CompletedDateKey = '20140131'
AND ArchiveQueueType = 0
AND PatientBucketItemCount <> 0
AND Exclude = 0
AND P.ENDDate is Null
This is the join I want to add to this select statement
left outer join
ssdba.excelleRx_WebFOCUS.dbo.DimHospiceHiearchy (nolock) h on b.groupid = h.group_id
You are not allowed to call a table valued function remotely (ie across servers).
There is a workaround here:
Workaround for calling table-valued function remotely in SQL Server has even more issues
And more info here:
http://social.msdn.microsoft.com/Forums/en-US/1f0d2885-faa2-496a-b010-edc441260138/remote-tablevalued-function-calls-are-not-allowed?forum=transactsql

SQL Query Optimization -Slowing the Server

The system I maintain seems to slow down quite a bit every few days, and I assume it's from a bad query somewhere.
From what I can tell, I've narrowed the issue down to a page or two. Here's the query on the page that I think is causing the issue.
select a.s_purchase_order as order_id, a.order_type, a.nobackorder, a.order_note, a.note, a.rqst_dlvry_date, b.customer_name ,c.store_name,(c.store_name + ',' + isnull(c.address1 + ',', ' ') + isnull(c.city + ',', ' ') + isnull(c.state_cd+ ',', ' ') + isnull( c.zipcode, ' ')) as store_info, d.supplier_account
from VW_CustomerOrder a, Customer b, Store c, eligible_supplier d
where a.customer = c.customer
and a.store = c.store
and a.customer = b.customer
and c.customer *= d.customer
and c.store *= d.store
and a.supplier *= d.supplier
and a.purchase_order = #order_id
and a.customer = #customer_id
and a.store=#store_id
and a.supplier = #supplier_id
Is there something obvious there that would be very slow or cause the system to slow over time?
what about do some inner joins to solve this, check your base and see index and foreign keys for those table, this always is helpful in querys and performance
select
a.columun_a, b.column_a from table_a a
inner join table_b b on a.id = b.id
where
b.column_b = "some value"