column ambigously defined error - sql

i have this code
select people_id,first_name
FROM people , PUBAUTHOR_PEOPLE
WHERE people.people_id = PUBAUTHOR_PEOPLE. people_id
and it says column ambigously defined does anybody know why and how to fix that?

It's complaining because both tables have a column called 'people_id', so you have to specify which table to read it from (even though it will be the same because of the join condition), so something like:
SELECT people.people_id,
first_name
FROM people, PUBAUTHOR_PEOPLE
WHERE people.people_id = PUBAUTHOR_PEOPLE.people_id

You should add table name before your coulmn names as below
select people.people_id,people.first_name
FROM people , PUBAUTHOR_PEOPLE
WHERE people.people_id = PUBAUTHOR_PEOPLE. people_id
I recommended you to use aliases as below to make code more readable
select p.people_id,p.first_name
FROM people p, PUBAUTHOR_PEOPLE pp
WHERE p.people_id = pp.people_id
I also recommended you to use joins as below
select p.people_id,p.first_name
FROM people p
join PUBAUTHOR_PEOPLE pp on p.people_id = pp.people_id
It is more readable now, isn't it?

Related

trouble with inner joining 2 tables

I have a database with 2 tables in it one is 'enlistments' and the other one is 'users'. In the enlistments table I have a user_id and in the users table I have a name. I want to get the name of the user which belongs to the id.
I know I need to do this with an inner join like this:
SELECT enlistments.round_id, users.name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.name
WHERE enlistments.activity_id = 1;
However I get this error: Warning: #1292 Truncated incorrect DOUBLE value
I did some research and found out it has to do with comparing an int with a string but I don't know how to solve the problem.
This is how my database looks like
join on is the condition you use to join the tables. Here it's enlistments.user_id=users.id.
select e.round_id
,u.name
from enlistments e join users u on u.id = e.user_id
where activity_id = 1
round_id
name
1
test2
Fiddle
To validate and be sure you are pulling back the exact data desired, I usually provide aliases for each column brought back and make sure to bring back the join columns also. It's good practice to label where the columns returned originated.
SELECT
Enlistments.UserID as Enlistments_UserID,
Users.ID as Users_ID,
enlistments.round_id as Enlistments_RoundID,
users.name as Users_Name
FROM enlistments
INNER JOIN users
ON enlistments.user_id=users.id
WHERE enlistments.activity_id = 1;
SELECT EN.round_id, US.name
FROM enlistments EN
INNER JOIN users US
ON US.name= CAST(EN.user_id AS VARCHAR)
WHERE EN.activity_id = 1
What you are needing is the function cast that can convert any kind of data into another, so you'll pass your integer value as the first argument followed by "AS '%DATATYPE'" where %DATATYPE is the kind of data you want to achieve.
In your case:
SELECT CAST(123456 AS VARCHAR)
-- RETURNS : '123456'
Anyway, I’m not sure that you can be able to join these two tables with the join you are using.
For more help please share some data.

On an SQL Select, how do i avoid getting 0 results if I want to query for optional data in another table?

I have a table with Customers which includes their contact person in the helpdesk. I have another table that lists all vacancies of the helpdesk employees - if they are currently sick or on vacation etc.
I need to get the helpdesk contact and the start/end time of their vacation IF there is an entry.
I currently have this (simplified):
SELECT *
FROM dbo.Customers, dbo.Projects, dbo.Vacations
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
AND dbo.Projects.HDContactID = dbo.Vacations.HDContactID
So if there is a vacation listed in the Vacations table, it works fine, but if there is no vacation at all, this will not return anything - what i want is that if there is no vacation, it simply returns the other data, and ignores the missing data (returns NULL, doesn't return anything, not important)
In any case, I need to get the Customers and Project data, even if the query can't find an entry in the Vacations table. How would I do this? I pretty new to SQL and couldn't find a similar question on this site
EDIT: I'm using SQL Server, currently using HeidiSQL
Try below query:
SELECT * FROM dbo.Customers, dbo.Projects
left join dbo.Vacations on dbo.Projects.HDContactID = dbo.Vacations.HDContactID
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
Use left join as mentioned by #Flying Thunder,
Example of the left join:
SELECT country.country_name_eng, city.city_name, customer.customer_name
FROM customer
LEFT JOIN city ON customer.city_id = city.id
LEFT JOIN country ON city.country_id = country.id;
You can find a nice guide for the joins and SQL here:
https://www.sqlshack.com/learn-sql-join-multiple-tables/
You should be using LEFT JOIN. In fact, you should never be using commas in the FROM clause. That is just archaic syntax and closes the powerful world of JOINs from your queries.
I also recommend using table aliases that are abbreviations of table names. The best are abbreviations for the table names:
SELECT *
FROM dbo.Customers c LEFT JOIN
dbo.Projects p
ON c.CustomerID = p.CustomerID LEFT JOIN
dbo.Vacations v
ON p.HDContactID = v.HDContactID
WHERE c.Phone = $Phone;
Have you try this to skip vacation record if not present like this:
SELECT * FROM dbo.Customers, dbo.Projects, dbo.Vacations
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
AND (dbo.Vacations.HDContactID IS NULL OR dbo.Projects.HDContactID = dbo.Vacations.HDContactID)

Problem accessing specific column using INNER JOIN

I have two tables Listings & Reviews that both have a column id.
I want to inner join them with Listings.id = Reviews.listing_id but when I am specifying something in my pgadmin, like listings.id or example.example it seems like it doesn't recognise it.
I get the error:
missing FROM-clause entry for table "listings"
Do I write something wrong?
Here is the code:
SELECT
id, listing_url, reviewer_id, reviewer
FROM
public."Listings"
INNER JOIN public."Reviews" ON Listings.id = listing_id
WHERE
reviewer = 'Vivek'
order by
reviewer_id;
Always qualify all columns names so both you and the SQL engine know where the columns come from. It is not clear where the columns come from. I've made guesses on where the columns come from:
SELECT l.id, l.listing_url, r.reviewer_id, r.reviewer
FROM public."Listings" l INNER JOIN
public."Reviews" r
ON l.id = r.listing_id
WHERE r.reviewer = 'Vivek'
ORDER BY r.reviewer_id;
Note that this introduces table aliases, which are abbreviations for tables. This makes it easier to qualify the column names (the default alias is the full table name).
Also, I may be wrong on where the columns come from; your question does not have complete information on the table structure.

SQL - Nested Sub-Queries

Using postgresql, I have to create a view called 'no_cat_customers' that returns the first name, last name of any customer who has not been shipped any edition of the book named 'The Cat in the Hat'. This should be done using universal quantification. The error I'm getting is - "ERROR: EXCEPT types integer and text cannot be matched" in reference to line 7 (EXCEPT (SELECT shipments.isbn).
CREATE VIEW no_cat_customers(customer_first_name, customer_last_name)
AS SELECT first_name, last_name
FROM customers
WHERE EXISTS (SELECT c_id
FROM shipments
WHERE customers.c_id = shipments.c_id
EXCEPT (SELECT shipments.isbn
FROM books, editions, shipments
WHERE books.book_id = editions.book_id AND
editions.isbn = shipments.isbn AND
title LIKE '%The Cat in the Hat%'));
I understand that this is hard to ask considering you don't have the database I'm using, but any help with this would be very much appreciated!
EDIT: I should add that there is two editions of 'The Cat in the Hat' in the database, both with different isbn's. So that has to be taken into account.
Use explicit JOIN syntax instead of mixing it with real conditions in where clause. I believe that this should work:
CREATE VIEW no_cat_customers(customer_first_name, customer_last_name) AS
SELECT first_name, last_name
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM shipments s
JOIN editions e ON s.isbn = e.isbn
JOIN books b ON b.book_id = e.book_id
WHERE b.title ILIKE '%The Cat in the Hat%'
AND c.c_id = s.c_id
)
If you have datatype errors, cast your columns to appropriate types before comparing them.

What does joining with on a table twice on column as different aliases mean?

I only know basic SQL but the project that I am working on uses pretty complex queries. There is one query that I can't understand. The tables and fields of concern are people and person_details and the executable part of an even dirtier query is:
SELECT people.first_name
, people.last_name
, person_statuses.name as person_status
, companies.name as company_name
, person_roles.name as role
, person_role_memberships.event_name as membership_year
, person_role_memberships.start_date as start_date
, person_role_memberships.end_date as end_date
, person_role_memberships.sponsor_parent_company as sponsor_parent_company
, person_role_memberships.former_sponsor_parent_company as former_sponsor_parent_company
, person_role_memberships.workshop as workshop
FROM people
, *person_details as business_details*
, *person_details*
, person_roles
, person_role_memberships
, companies
, person_statuses
, companies as parent_companies
WHERE person_role_memberships.person_id = people.id
AND person_role_memberships.person_role_id = person_roles.id
AND
business_details.type = 'BusinessDetail'
and business_details.person_id = people.id
AND person_details.type = 'PersonalDetail'
and person_details.person_id = people.id
AND people.person_status_id = person_statuses.id
AND ifnull(companies.parent_id, companies.id) = parent_companies.id
AND people.company_id = companies.id
AND companies.name = 'Pak Qatar'
AND people.last_name = 'Aslam'
limit 100;
I want to know what is the logic that the bold part of the where clause is creating. Is it, because of the AND keyword, only allowing those persons, which have BusinessDetail as well as PersonalDetails is the person_details table?
It's probably a self join. It's usually used when you have a relation (table) relating with itself (employees <-> boss), or when a relation (table) is used to store different kind of information for a certain row.
In your example, table person_details is being used to store business and person information. The join is:
business_details.person_id = people.id
AND person_details.type = 'PersonalDetail'
AND person_details.person_id = people.id
So I would say that person_details table holds business and person information on different rows for the same people.id row in people table.
It's basically saying:
The person MUST have a business_details record which MUST be of type 'BusinessDetails' AND the person MUST have a person_details record which MUST be of the type 'PersonalDetail' It looks like both are stored in the same table (business_details is an alias of the person_details table), so its joining to the table twice to check for both conditions.
I'm not sure what flavour of SQL this is (SQL Server/Oracle etc) but the query could probably be written out a little neater using proper join syntax (although the syntax used will create joins under the hood, its not as easy to read as something with explicit join syntax).