SQL server -Multiple address joins in from clause - sql-server

Ok, so I might be trying to do this all wrong, but here it goes.
In my data I have customer seq which is where the order was shipped to. But, since some orders are dropped shipped they have a different customer number and seq kept in a different table.
So basically, I want to say
if custaddr.country <> "" then custaddr.country, else DR.country
the from clause I currently have looks like this
CO is order table
Coitem is line of order
co_ship is shipped line
custaddr is customer address
if the order is drop ship, the customer and seq is pulled from coitem instead of co.
from
co inner join coitem on co.co_num = coitem.co_num
inner join co_ship on (co_ship.co_num = coitem.co_num and co_ship.co_line = coitem.co_line and co_ship.co_release = coitem.co_release)
inner join custaddr on (co.cust_num = custaddr.cust_num and co.cust_seq = custaddr.cust_seq)
inner join custaddr DR on (coitem.cust_num = custaddr.cust_num and coitem.cust_seq = custaddr.cust_seq)
when I run this, with the last inner join active I get no results.

Related

Multiple INNER JOIN SELECT query not returning data

This is a stored procedure to select the full details of a wine.
It takes as a parameter a storage location ID.
This builds properly and is similar in structure to many sp's I have written that work,
however it returns no data. Is there something I am missing?
CREATE PROCEDURE [sp_retrieveInventory_Full]
(
#StorageLocationID [int]
)
AS
BEGIN
SELECT [WineName],
[RackID],
[RackColumn],
[RackRow],
[WineTypeID],
[WineVarietyID],
[VintnerName],
[dbo].[Vintner].[Country],
[dbo].[Vintner].[StateProvince],
[dbo].[Vintner].[Region],
[VendorName],
[Vintage],
[PurchaseDate],
[PurchasePrice],
[BottleSizeID],
[ABV],
[DrinkByDate],
[FoodType],
[TastingNotes],
[RatedBy],
[RatingScore]
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
INNER JOIN [dbo].[Rating]
ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
END
GO
When a query reruns no result it's because no records exists that satisfy the conditions in it's where clause, or, in case of queries that contains inner joins, at least one of the joins on condition returns no records.
The easiest way to figure out what join is messing up your query is to start removing the joins one by one, but to do that, you have to first change the select clause.
What I like to do is this: Start with all the joins except the last one - see if it returns any records:
SELECT 1
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
-- INNER JOIN [dbo].[Rating]
-- ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
If not, comment out the next join and run the query again. Rinse and repeat.
Please note, however, that there might be more than one inner join that prevents the query from returning records.

SQL Server 2008: Only one result, joining 3 tables

I have the following databases:
IMAGE UPDATED
SELECT
l.FECHA, nc.IdNumeroControlTrabajador AS ENLACE,
t.RFC, t.Homonimia AS HOM,
t.ApellidoPaterno, t.ApellidoMaterno,
t.Nombre, l.IMPORTE,
cp.NombreOrgano AS DEPENDENCIA, l.OBSERVACIONES,
l.FECHA_INICIAL, l.FECHA_FINAL,
MAX (cn.FechaIngresoGobierno)
FROM
CapturaFAIFAP.dbo.Laudos AS l
LEFT JOIN FAIFAPparalelo.dbo.NumeroControlTrabajadores AS nc ON l.ID = nc.idTrabajador
LEFT JOIN FAIFAPparalelo.dbo.ClaveNominalTrabajadores AS cn ON l.ID = cn.idTrabajador
LEFT JOIN FAIFAPparalelo.dbo.Trabajadores AS t ON l.ID = t.idTrabajador
LEFT JOIN FAIFAPparalelo.dbo.ClaveProgramatica AS cp ON cn.idClaveProgramatica = cp.idClaveProgramatica
LEFT JOIN (
SELECT
cp.NombreOrgano,
MAX (cnt.FechaIngresoGobierno) AS fecha
FROM
FAIFAPparalelo.dbo.ClaveNominalTrabajadores as cnt
GROUP BY
cp.NombreOrgano
) AS j ON (
cp.NombreOrgano = j.NombreOrgano
AND j.fecha = cn.FechaIngresoGobierno
)
GROUP BY
l.FECHA, nc.IdNumeroControlTrabajador, t.RFC,
t.Homonimia, t.ApellidoPaterno, t.ApellidoMaterno,
t.Nombre,l.IMPORTE,cp.NombreOrgano,l.OBSERVACIONES,
l.FECHA_INICIAL,l.FECHA_FINAL,cn.FechaIngresoGobierno
I need to unify the query. The huge query i put in code, and a similar query in the image. If i join the tables ClaveNominal and ClaveProgramatica i have duplicities, because sometimes the persons have 2 ClavesProgramaticas, due to the system I use, not delete or update the current registry, just puts in inactive and adds a new one active, and i can't make the condition to activo because, that represents if the person still works here.

MS SQL Table Joins - Multiple Tables

I am new to MS SQL and am having trouble joining 4 tables within a query.
I am trying to join Orders, Order Lines, Client, and Picked tables to create a query to show quantity ordered and picked for a client. If I comment out the last inner join for Picked, I get the correct results. When I include the inner join for Picked the query returns results but data that should be in the Picked fields is NULL. One order line can have 1 or more Picked lines.
SELECT W_Warehouse, OH.OrderID, OH.RequiredDate, C.Client, OL.LineNbr, OL.QtyOrd, P.QtyPick
FROM Order
INNER JOIN Warehouse on Order.OH_WHS = Warehouse.W_PK
INNER JOIN Client on Order.O_Client = Client.C_PK
INNER JOIN OrderLine on Order.O_PK = OrderLine.OL_PK
INNER JOIN Picked on OrderLine.O_PK = Picked.P_PK
WHERE C.CLIENT = 'WENDYS'
Without knowing the data in the tables it is difficult to answer precisely.
But as you say you have 1+ rows in the Picked table, you probably want to do aggregation with GROUP BY and SUM()
Maybe this is what you're looking for:
SELECT
W.W_Warehouse,
OH.OrderID,
OH.RequiredDate,
C.Client,
OL.LineNbr,
OL.QtyOrd,
P.QtyPick
FROM
Order OH
INNER JOIN Warehouse W on OH.OH_WHS = W.W_PK
INNER JOIN Client C on OH.O_Client = C.C_PK
INNER JOIN OrderLine OL on OH.O_PK = OL.OL_PK
CROSS APPLY (
select sum(QtyPick) as QtyPick
from Picked P
where OL.O_PK = P.P_PK
) P
WHERE
C.CLIENT = 'WENDYS'
It calculates the sum of QtyPick separately so it doesn't increase the number of lines in the result.

How to join additional table when left outer not working

I have an existing proc which I have chopped up for brevity's sake
SELECT col1, col2
FROM (
col1, col2
SELECT col3--aggregate columns
FROM iep i
INNER JOIN student s ON s.studentID = i.studentID
INNER JOIN dbo.IDuration id ON i.IepID = id.iepID
INNER JOIN AppointmentStudent as ON s.studentID = as.studentID
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
WHERE s.studentID = #studentID
GROUP BY col1, col2
) t
The aggregate columns summarizes appointments into the weeks of the year, but it only does sos for the weeks the student had appointments. I have an additional table called SchoolWeekYear that is populated with all of the weeks of the year that I am trying to integrate to this proc so I get 52 records back and not just the handful I am currently getting.
SELECT col1, col2
FROM (
col1, col2
SELECT col3--aggregate columns
FROM iep i
INNER JOIN student s ON s.studentID = i.studentID
INNER JOIN dbo.IDuration id ON i.IepID = id.iepID
INNER JOIN AppointmentStudent as ON s.studentID = as.studentID
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
LEFT OUTER JOIN SchoolWeekYear swy on a.calWeekNumber = swy.calWeekNumber
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
WHERE s.studentID = #studentID
GROUP BY col1, col2
) t
Is this possible?
You need to integrate SchoolWeekYear into the existing table set at an earlier stage.
To show you the principle, let us simplify the problem even further. Let there be a table called WeeklyData with columns WeekNumber and SomeData. Some weeks might have multiple entries, some others none. So this query
SELECT
WeekNumber,
AGG(SomeData)
FROM
WeeklyData
GROUP BY
WeekNumber
;
would return only weeks present in WeeklyData. If you want to return data for all weeks, use a corresponding reference table (let it be called AllWeeks) like this:
SELECT
aw.WeekNumber,
AGG(wd.SomeData)
FROM
AllWeeks AS aw
LEFT JOIN
WeeklyData AS wd ON aw.WeekNumber = wd.WeekNumber
GROUP BY
aw.WeekNumber
;
So, you take the reference table (AllWeeks) and join the data table (WeeklyData) to it, not the other round.
Now, what if the original query was slightly more complex? Let us now suppose the data table is called StudentWeeklyData and has a column called StudentID which is a reference to a Students table. Let us also imagine the query is similar to yours in that it logically includes the Students table before the data table is joined and filters the results on the primary key of Students:
SELECT
s.StudentID,
s.StudentName,
swd.WeekNumber,
AGG(swd.SomeData)
FROM
Students AS s
INNER JOIN
StudentWeeklyData AS swd ON s.StudentID = swd.StudentID
WHERE
s.StudentID = #StudentID
GROUP BY
s.StudentID,
s.StudentName,
swd.WeekNumber
;
(Not every detail matters here, I just wanted to use a more similar example for you that would still be simple enough to understand.) Again, this would return only weeks where the specified student has data in StudentWeeklyTable. If you wanted to return all weeks for the student (some of them potentially empty, of course), this is how you could go about it:
SELECT
s.StudentID,
s.StudentName,
aw.WeekNumber,
AGG(swd.SomeData)
FROM
Students AS s
CROSS JOIN
AllWeeks AS aw
LEFT JOIN
StudentWeeklyData AS swd ON s.StudentID = swd.StudentID
AND aw.WeekNumber = swd.WeekNumber
WHERE
s.StudentID = #StudentID
GROUP BY
s.StudentID,
s.StudentName,
aw.WeekNumber
;
Here you can see again that the AllWeeks table is included before the data table. The difference to the previous case is we are not left-joining the result of the join between Students and StudentWeekly to AllWeeks, nor are we left-joining the data table itself specifically to AllWeeks. Instead, the data table is joined to the result of a cross join, Students × AllWeeks.
Returning to your specific situation, I realise that in your case even more tables are involved. Since you are not specifying how all those tables are related to one another, I can only guess that SchoolWeekYear should be cross-joined somewhere after FROM and before this line:
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
and that the said line should be modified like this:
LEFT JOIN Appointment a ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
the swy being an alias assigned to SchoolWeekYear.
It is also worth noting that there is a subsequent inner join with AppointmentTherapist. That join would eliminate the effect of the above left join if it remained unchanged, because its condition references the Appointment table. Perhaps, the syntactically easiest way to fix the issue would be to change that inner join to a left one too, although there is another way: instead of
LEFT JOIN Appointment a ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
LEFT JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
you could use this syntax:
LEFT JOIN
Appointment a
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
That way the logical order of joining would be changed: Appointment and AppointmentTherapist would be first inner-joined with each other, then the result set would be outer-joined to the result of the previously specified joins.
It is possible. But if you have multiple row with some calWeekNumber on the SchoolWeekYear table, your aggregate function return wrong result.
If you want all lines in SchoolWeekYear shown, regardless of a match, you should use RIGHT OUTER JOIN instead of LEFT.

formulating an SSRS query to include zero/empty rows in a GROUP BY

I'm working on a SSRS report and I'm having an issue with my Plant name not showing when there is no data available for the date range selected.
The far left column, first row (technically the 2nd by the image) is where my plant name should appear at all times:
Essentially the first image showed just my blank rows/columns. The first column, first row is where my plant name should be at all times. The remaining columns are my returned data based on date selection.
The second image would show everything working as it should when there is data.
I'm grouping by PlantCode in SSRS which is what gives my my plant name. I don't know how to get the plant name to appear even if there is not data available.
Is this possible?
I THOUGHT I could use something like iif(salesvolume is NOTHING, [PlantCODE],[PlantCode])
Here is the database query for the report
SELECT
PInv.[Plant_Numer],
PInv.[Plant_Code],
PInv.{Department_number],
PInv.[Inventory_Volume],
Pinv.[Inventory_Date], -- 'Last Inventory Date'
pls.[Actual_Volume],
pls.[Budget_Volume],
ppf.[Good_Output_Product_Units] AS 'Production Volume', -- 'Next Day Production
CASE
WHEN coalesce (pls.[Acutal_Volume],0) = 0 and coalesce (pls.[Actual_Sales_Dollars],0) = 0 THEN 0
ELSE ((pls.[Actual_Sales_Dollars/pls.[Actual_Volume])) AS 'Average Price' -- 'Next Day Sales'
FROM
[TrueOpportunity].[dbo].[Production_Fact] pf
inner join [TrueOpportunity].[dbo].[Production_Process_Fact] ppf on ppf.production_number = pf.production_number
inner join [TrueOpportunity].[dbo].[Process] prc on prc.process_number = pf.process_number
inner join [TrueOpportunity].[dbo].[Department] dpt on dpt.department_number = prc.department_number
inner join [WoodProduction_New].[dbo].[Plywood_Layup_Sales] pls on pls.procesS_number = pf.procesS_number
inner join [WoodProduction_New].[dbo].[Process_Inventory] Pinv on PInv.[Inventory_Date] = pf.date
and pls.product_date = pf.date
and dpt.department_number = pinv.department_number
WHERE
pf.date between #BeginningDate and #EndingDate
I think you want to change your query so that Process Inventory is your primary table and all other tables are LEFT JOINED to that table. That way the Plant Number & Code will show up regardless of whether there is matching data in the other tables.
This syntax is probably not completely correct, but I would start out by changing your FROM clause to look something like this:
FROM
[WoodProduction_New].[dbo].[Process_Inventory] Pinv
LEFT JOIN [TrueOpportunity].[dbo].[Production_Fact] pf
ON PInv.[Inventory_Date] = pf.date
LEFT JOIN [TrueOpportunity].[dbo].[Production_Process_Fact] ppf
ON ppf.production_number = pf.production_number
LEFT JOIN [TrueOpportunity].[dbo].[Process] prc
ON prc.process_number = pf.process_number
LEFT JOIN [TrueOpportunity].[dbo].[Department] dpt
ON dpt.department_number = prc.department_number
AND dpt.department_number = pinv.department_number
LEFT JOIN [WoodProduction_New].[dbo].[Plywood_Layup_Sales] pls
ON pls.process_number = pf.process_number
AND pls.product_date = pf.date
Experiment with that and see if you can get it to display the data that you want.

Resources