I'm trying to build a sql query which worked for the previous one which had 2 tables and it was pretty straight forward. This one though, has been driving me insane for 6 hours now.
The problem I have is that the results are only displayed should ALL criteria match and I don't want that. I would like the field to result back blank if it does not have an entry in the database.
I have a table and I want to display the orderrefno. At this point I want to check to see if a delivery note has been created and if so, I want to then see if an invoice has been created. Then report back to the report with the numbers of each but if they don't exist, the. It should just have the order no and the others would be both blank or just the invoice would be blank, should a delivery note been done.
I've tried building a query in crystal using inner, left join, right join, full but if an invoice does NOT exist I want it to list the delivery no and order no, but it won't.
I can do this in datasources and master sources in delphi and v studio, but would like to do a sql because the other easy is slow.
My tables are
Project
Order
Calloff
Calltodeliverylink
Delivery
Deliverytoinvoicelink
Invoice
Tables are linked as follows.
Project.id is the main point of entry.
Then
Order.projectid -- project.id
Calloff.orderid -- order.id
Callofftodeliverylink.deliveryid -- call off.id
Delivery.id -- callofftodeliverylink.deliveryid
Deliverytoinvoicelink.deliveryid -- delivery.id
Invoice.id -- deliverytoinvoicelink.invoiceid
Many many thanks
EDIT:
Added Code. Sorry for FROM section being a mess. In crystal drew the linking fields and asked it to show me the query and this is what it gave me.
SELECT
"Projects"."ID", "Orders"."IntOrderNo", "Deliveries"."DeliveryNo", "Projects"."InternalRef",
"CallOffs"."ID", "Customers"."Name", "Contacts"."Name", "Invoices"."InvoiceNo"
FROM
{oj (((((("GNManager"."dbo"."Invoices" "Invoices" LEFT OUTER JOIN "GNManager"."dbo"."DeliveryToInvoiceLink" "DeliveryToInvoiceLink" ON "Invoices"."ID"="DeliveryToInvoiceLink"."InvoiceID") LEFT OUTER JOIN "GNManager"."dbo"."Deliveries" "Deliveries" ON "DeliveryToInvoiceLink"."DeliveryID"="Deliveries"."ID") LEFT OUTER JOIN "GNManager"."dbo"."CallOffToDeliveryLink" "CallOffToDeliveryLink" ON "Deliveries"."ID"="CallOffToDeliveryLink"."DeliveryID") LEFT OUTER JOIN "GNManager"."dbo"."CallOffs" "CallOffs" ON "CallOffToDeliveryLink"."CallOffID"="CallOffs"."ID") LEFT OUTER JOIN ("GNManager"."dbo"."Projects" "Projects" LEFT OUTER JOIN "GNManager"."dbo"."Orders" "Orders" ON "Projects"."ID"="Orders"."ProjectID") ON "CallOffs"."OrderID"="Orders"."ID") INNER JOIN "GNManager"."dbo"."Customers" "Customers" ON "Orders"."CustomerID"="Customers"."ID") INNER JOIN "GNManager"."dbo"."Contacts" "Contacts" ON "Orders"."ContactID"="Contacts"."ID"}
WHERE
"Projects"."InternalRef"='12/4169'
ORDER BY
"Projects"."InternalRef" DESC, "Orders"."IntOrderNo" DESC
The above statement does work and produces everything that I need, but only if Invoices has an entry. If invoices is blank, nothing gets displayed.
The order of the tables in your join statement is the issue. Invoices being the first table is the one that will drive the rest of the results.
If you need all orders associated with your projects, no matter if there are any invoices, here's what I would do. Please note that you need valid values in Projects, Orders, Customers and Contacts, but everything else could be null.
select
Projects.ID
,Orders.IntOrderNo
,Deliveries.DeliveryNo
,Projects.InternalRef
,CallOffs.ID
,Customers.Name
,Contacts.Name
,Invoices.InvoiceNo
from
Projects
join Orders on Orders.ProjectID = Projects.ID
join Customers on Orders.CustomerID = Customers.ID
join Contacts on Orders.ContactID = Contacts.ID
left join Callofs on Callofs.OrderID = Orders.ID
left join CallOffToDeliveryLink on CallOffToDeliveryLink.CallOffID = Callofs.ID
left join Deliveries on CallOffToDeliveryLink.DeliveryID = Deliveries.ID
left join DeliveryToInvoiceLink on DeliveryToInvoiceLink.DeliveryID = Deliveries.ID
left join Invoices on DeliveryToInvoiceLink.InvoiceID = Invoices.ID
where
Projects.InternalRef = '12/4169'
order by
Projects.InternalRef desc
,Orders.IntOrderNo desc
Related
I'm having an issue where I'm getting some incorrect values in my output. I am binding the below highlighted table column with the circled column down the bottom. The service_id on the highlighted column is what is unique, but I need to bind the booking_id to retrieve the info (if that makes sense. What I end up getting is the top table where I get repeats, or the price is wrong. I should be getting only 5 lines in the top table.
Here's my code. I suspect I might be doing the join wrong?
SELECT bad.agent as Agents,
dog.SUPPLIER as SUPPLIER,
bad.status as TheStatus,
country.analysis_master1 as Country,
ftb.booking_actual_retail as BookingActualRetail,
ftb.Booking_Actual_Cost as BookingCost,
ftb.Booking_Actual_Retail_inc as BookingRetailINC,
fts.Service_Id,
fts.Service_Actual_Retail_inc as ServiceActualCostInc,
Product.SERVICE,
Product.SL_STATUS as SLSTATUS,
cat.name as Product2,
bad.LAST_SERVICE_DATE as Servicedate,
bad.LW_DATE as LWDATE,
ftb.Entered_Date as DATEENTERED,
ftb.Booking_Pax as PEOPLE,
ftb.Booking_Children as KIDS,
bad.TRAVELDATE as TRAVELDATE,
bad.FULL_REFERENCE
from BHD bad
inner join FTB on bad.FULL_REFERENCE = ftb.booking_reference
inner join FTS on FTB.Booking_Id = fts.Booking_Id
inner join DRM Country on bad.agent = country.code
inner join BSL Product on bad.BHD_ID = Product.BHD_ID
inner join SRV cat on Product.SERVICE = cat.CODE
inner join OPT dog on Product.OPT_ID = dog.OPT_ID
where bad.STATUS = 'IV' AND bad.FULL_REFERENCE = 'LTIT129488'
UPDATE:
Ok, so it looks like this join here causes the multiple outputs:
inner join FTS on FTB.Booking_Id = fts.Booking_Id
I have included the two tables, their headers, and sample data
You have somewhere put the join for the service or supplier in the wrong way.. Please check this line again.
inner join SRV cat on Product.SERVICE = cat.CODE
UPDATED SOLUTION :
As per your updated screenshots, I found the issue...
you have joined like this.
inner join FTB on bad.FULL_REFERENCE = ftb.booking_reference
In this join, your one table has single record against booking reference while another have multiple records against booking refrence. Thats why you are getting the multiple records in the output.
Remove this join and your problem will be solved. If you really want the data from this table then you can select in other way like using outer apply etc.
I'm writing a report that includes sales order info + delivery notes. What I'm trying to do is add information from the purchase orders (ex. PO # & Price) table (I believe it is OPOR). How do I link this table to one or more of the tables I already have? Please see my query below:
SELECT o0.NumAtCard AS OrderNo
,i0.DocNum
,i0.TrackNo AS TrackingNo
,i0.CardName
, o0.DocNum AS DelivDoc
FROM ODLN d0
INNER JOIN DLN1 d1 ON d0.DocEntry = d1.DocEntry
LEFT OUTER JOIN INV1 i1 ON d1.TrgetEntry = i1.DocEntry
LEFT OUTER JOIN OINV i0 ON i1.DocEntry = i0.DocEntry
INNER JOIN ORDR o0 ON d1.BaseEntry = o0.DocEntry
INNER JOIN OITM itm ON i1.ItemCode = itm.ItemCode
WHERE o0.CANCELED = 'N' AND
i0.TrackNo IS NOT NULL
GROUP BY o0.NumAtCard
|,i0.DocNum
|,i0.TrackNo
,i0.CardName
,o0.DocNum
ORDER BY o0.NumAtCard
Ok so on the back and forth, it is clear the real question is about how to go about adding the information to the query.
A SQL consists of several major pieces in order:
The column list
The table/join specification (FROM and JOIN clauses)
The where section (WHERE...)
Aggregate rules (GROUP BY/Having)
Limit and offset (LIMIT/OFFSET)
In your case you need to start by identifying the information in the database you want to add, and how it relates to what you have already. So in this case you are going to:
Add the columns as necessary to the column list (the part between SELECT and FROM)
Add the table to the join list (via a LEFT JOIN, with the join condition following ON). So if you have a so_docnum field that matches the sales order docnum field it would be something like LEFT OUTER JOIN OPOR po ON po.so_docnum = o0.docnum)
Add anything needed to the GROUP BY clause (probably the fields you are adding from the PO).
However, your first step is to map out the data so that these steps can be executed because it is clear you don't have all the information you need to add it yet.
I am trying to set up a view in a database I want to see all the data in the PERSON table and three columns from the NON_PERSONNEL table for a program from the PROGRAM table. This is what I am trying now, the query runs without errors but doesnt give me any results. All 4 of the tables listed below are imperative to derive the answer
SELECT
person.*,
non_personnel.description,
non_personnel.amount
FROM
person,
non_personnel,
personnel_role,
programs
WHERE
person.person_id = personnel_role.person_id
AND personnel_role.program_id = programs.program_id
AND programs.program_id = non_personnel.program_id
AND programs.program_name = 'Fake Program'
you need to use left join, so you get all persons but description and amount can be NULL if that person doesn't have records in other tables
Also use explicit join syntax.
SELECT person.*, non_personnel.description, non_personnel.amount
FROM person
left join personnel_role
ON person.person_id = personnel_role.person_id
left join programs
ON personnel_role.program_id = programs.program_id
AND programs.program_name = 'Fake Program'
left join non_personnel
ON programs.program_id = non_personnel.program_id
This really depends on your schema and the data in the tables. The way you have it written now means that only records that match in every table (according to your WHERE conditions) are passed into the result set.
This means that you have to have all program_id's in your programs table that you want returned in the results ALSO in your non_personnel table. They must also ALL be in your personnel_role table. And all person_ids in your personnel_role table must be in the person table. You get no results back, so this is probably not what you meant to write.
My guess is that you want to use a LEFT OUTER JOIN here. LEFT OUTER JOIN says "Take all records from one table and ONLY records from the joined table that meet the criteria in your ON statement".
Because you are wanting information based on a particular Program, chances are you want to start with that table:
SELECT person.*,
non_personnel.description,
non_personnel.amount
FROM
programs
LEFT OUTER JOIN personnel_role ON
programs.program_id = personnel_role.program_id
LEFT OUTER JOIN person ON
personnel_role.person_id = person.person_id
LEFT OUTER JOIN non_personnel
programs.program_id = non_personnel.program_id
WHERE
programs.program_name = 'Fake Program'
This is a bit of an assumption since I have no idea what your schema is or how your data is built, but I'm betting it's what you are after.
What this FROM clause says is:
1. Take all records from Program (where program_name = 'fake program') and only reocrds from personnel_role that share the same program_id
2. Take only the records from person where the person_id matches the records we just got from the personnel_role table
3. Take only the records from non_personnel where it shares a program_id with the results from the program table.
I'm having a little confusion with a certain example.
I am supposed to list all orders and their corresponding details.
This is what I'm doing:
SELECT *
FROM Orders
LEFT OUTER JOIN [Order Details]
ON Orders.OrderID=[Order Details].OrderID;
This gives the number of rows = 2155.
Now the problem is, the number of rows in Orders Table is 830...how can left outer join create more rows ?
By definition of left outer join, all the rows from the left table are taken and matching records from the second table are added.
I checked the number of rows in the Order Details table..that is 2155.
Why is left outer join using all rows from Order Details table?
LEFT JOIN takes all the details from the table you define on the left side of the join and match records from the right table.
If there's no match, all columns of the right table have NULL values.
If there's a match, all matching records from the right table are returned. If your relationship is 1-to-many (as in your case), it means that there may be more than one record returned from the right table for each record in the left table.
LEFT OUTER JOIN will match all records in the right table, just as an INNER JOIN will. The difference is a LEFT JOIN will preserve records from the left table with no match in the right table.
In this scenario, all records in [ORDER DETAILS] have a corresponding entry in ORDERS, which is why the total number of records matches the number of rows in ORDER DETAILS
Based on the table descriptions, this is exactly what you want. Having an ORDER DETAIL without an ORDER would be a much more serious issue.
Basically I want to take all the names (RequiredAccount, RequiredContact, RequiredOwner) for all the rows with a matching activityid and put them in there own column. So in short, I want to take multiple rows of data and put them in a Column. Basically I want to do what this person is doing (http://www.sqlprof.com/blogs/sqldev/archive/2008/03/31/how-to-list-multiple-rows-of-data-on-same-line.aspx) but I can't seem to get it to work.
SELECT DISTINCT
Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName,
Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner,
Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask,
Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
FROM
Contact AS Contact_1 RIGHT OUTER JOIN
Account RIGHT OUTER JOIN
SystemUser RIGHT OUTER JOIN
Appointment INNER JOIN
ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
Contact ON Appointment.new_ContactPerson = Contact.ContactId
And what I want if for the three Required columns to be in one column if there ActivityID Matches. So the first two rows would have two names in the new column.
Any ideas, help, etc.
Big Thanks!
Simulating group_concat in sql server 2005
There are a couple of working examples in that thread, none of them are very pretty though :-/