How do you combine multiple rows of data on same line - sql

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 :-/

Related

SQL query wrong index when where on join

I have a query with joins that is not using the index that would be the best match and I am looking for help to correct this.
I have the following query:
select
equipment.name,purchaselines.description,contacts.name,vendors.accountNumber
from purchaselines
left join vendors on vendors.id = purchaselines.vendorId
left join contacts on contacts.id = vendors.contactId
left join equipment on equipment.id = purchaselines.equipmentId
where contacts.id = 12345
The table purchaselines has an index on the column vendorId, which is the proper index to use. When the query is run, I know the value of contacts.id which is joined to vendors.contactId which is joined to purchaselines.vendorId.
What is the proper way to run this query? Currently, no index is used on the table purchaselines.
If you are intending to query a specific contact, I would put THAT first since that is the primary basis. Additionally, you had left-joins to the other tables (vendors, contacts, equipment). So by having a WHERE clause to the CONTACTS table forces the equation to become an INNER JOIN, thus REQUIRING.
That said, I would try to rewrite the query as (also using aliases for simplified readability of longer table names)
select
equipment.name,
purchaselines.description,
contacts.name,
vendors.accountNumber
from
contacts c
join vendors v
on c.id = v.contactid
join purchaselines pl
on v.id = pl.vendorid
join equipment e
on pl.equipmentid = e.id
where
c.id = 12345
Also notice the indentation of the JOINs helps readability (IMO) to see how/where each table gets to the next in a more hierarchical manner. They are all regular inner JOIN context.
So, the customer ID will be the first / fastest, then to vendors by that contact ID which should optimize the join to that. Then, I would expect the purchase lines to have an index on vendorid optimizing that. And finally, the equipment table on ITs PK.
FEEDBACK Basic JOIN clarification.
JOIN is just the explicit statement of how two tables are related. By listing them left-side and right-side and the join condition showing on what relationship is between them is all.
Now, in your data example, each table is subsequently nested under the one prior. It is quite common though that one table may link to multiple other tables. For example an employee. A customer could have an ethnicity ID linking to an ethnicity lookup table, but also, a job position id also linking to a job position lookup table. That might look something like
select
e.name,
eth.ethnicity,
jp.jobPosition
from
employee e
join ethnicitiy eth
on e.ethnicityid = eth.id
join jobPosition jp
on e.jobPositionID = jp.id
Notice here that both ethnicity and jobPosition are at the same hierarchical level to the employee table scenario. If, for example, you wanted to further apply conditions that you only wanted certain types of employees, you can just add your logical additional conditions directly at the location of the join such as
join jobPosition jp
on e.jobPositionID = jp.id
AND jp.jobPosition = 'Manager'
This would get you a list of only those employees who are managers. You do not need to explictily add a WHERE condition if you already include it directly at the JOIN/ON criteria. This helps keeping the table-specific criteria at the join if you ever find yourself needing LEFT JOINs.

Trying to figure out a sql query to fetch the right data from multiple tables

So I have a database and I have 4 tables (admin, appointment, doctor, patient).
I only care about appointment, doctor and patient.
Diagram of these 3 tables:
What I want is based on a patients amka(int) to find all his appointments and show his name, surname and doctors name, surname.
I made this query:
(SELECT doctor.name, doctor.surname
FROM public.doctor
INNER JOIN public.appointment ON doctor.username = 'alouisot2')
union
(SELECT patient.name, patient.surname
FROM public.patient
INNER JOIN public.appointment ON patient.amka = '713783001');
The problem with this query is that it will only show appointments between this specific doctor and I just want to get all the doctors names and surnames.
Also I use postgresql.
I was trying to figure it out but I couldn't. I need to restructure the query but I cannot think how I would solve this problem.
If you have any idea on how to do achieve this I would really appreciate it.
Try this - properly join the three tables together (doctor to appointment based on the common username column, appointment to patient on the common amka column), and define the WHERE clause with your desired values:
SELECT
doctor.name, doctor.surname,
patient.name, patient.surname
FROM
public.doctor
INNER JOIN
public.appointment ON doctor.username = appointment.username
INNER JOIN
public.patient ON appointment.amka = patient.amka
WHERE
doctor.username = 'alouisot2'
AND patient.amka = '713783001';
this query just needs simple joins; you seem to have overcomplicated it a lot for some reason...
SELECT
patient.name,
patient.surname,
doctor.name,
doctor.surname
FROM public.patient
INNER JOIN public.appointment
ON patient.amka = appointment.amka
INNER JOIN public.doctor
ON appointment.username = doctor.username
WHERE patient.amka = '713783001'

Getting repeats of output, possibly doing a join wrong?

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.

SQL INNER JOIN without linked column

I have an UltraGrid displaying customer information in it. The way the database is set up, there are 2 tables. Customers and Customer_Addresses. I need to be able to display all of the columns from Customers as well as Town and Region from Customer_Addresses, but I'm under the impression that I'd need Town and Region columns in the Customer table to be able to do this? I've never used an INNER JOIN before so I'm not sure if this is true or not, so can anybody give me pointers on how to do this, or if I need the matching columns or not?
Does it even require an INNER JOIN, or is there an alternative way to do this?
Below are the design views of both of the tables - Is it possible to display Add4 and Add5 from Customer_Addresses with all of Customers?
As long as you have another key column you can use to link the tables (ex. ID_Column), it is better that you use LEFT JOIN.
Example:
SELECT c.col1, ... , c.colN, a.town, a.region FROM Customers c
LEFT JOIN Customer_Addresses a ON a.ID_Column = c.ID_Column
In order to clarify how JOIN types work, look at this picture:
In our case, using a LEFT JOIN will take all information from the Customers table, along with any found matching (on ID) information from Customer_Addresses table.
First of all you need some column in common in two tables, all what you have to do is:
CREATE TABLE all_things
AS
SELECT * (or columns that you want to have in the new table)
FROM Costumers AS a1
INNER JOIN Customer_Addresses AS a2 ON a1.column_in_common = a2.column_in_common
The point is what kind of join do you want.
If you can continue the process without having information in table Costumers or in table Customer_Addresses maybe you need OUTER JOIN or other kind of JOIN.

Viewing Data from two tables while linking multiple tables in SQL

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.