SQL INNER JOIN / Unknown column C.book in On Clause - mysql

https://www.db-fiddle.com/f/nCgygDjwYXZnWQ28LL7kMi/0
Goal:
Select copy.owner of people that own both books by "Scott Kelby" with different ISBN numbers
Hey guys, in order to derive the book table in the example on db-fiddle, I had actually used a bunch of inner join statements.
Now that I have acquired the book table how can I check that the c.owner owns both copies of the book?
I tried to use
SELECT DISTINCT
C.owner
FROM
copy C,
copy C1
INNER JOIN (
SELECT
B.authors,
B.ISBN13
FROM
book B
INNER JOIN(
SELECT
B1.authors
FROM
book B1
GROUP BY
B1.authors
HAVING (COUNT(B1.authors) > 1)
) B1
ON B.authors = B1.authors) B
ON C.book = B.ISBN13 AND C1.book = B.ISBN13 AND C1.book <> C.book;
However, if I try to reference to two table in the 2nd line of code, i will get the error unknown column in ON clause forcing me to remove copy C1 from the query.

You can try below -
select owner
from book b inner join copy c
on b.isbn13=c.book
group by owner
having count(distinct isbn13)=2

Related

Query to get data form different columns

I got a problem regarding my query, I cannot seem to get the right one to get the data I want. I've got the following tables I need to get data from:
app_exhibition
- id
- name
- form_id
app_forms
- id
- name
app_languages
- id
- name
- code
app_link_lang
- id
- form_id
- lang_id
I want to select the name of the exhibition (app_exhibition) the id and name of the form (app_forms) the name of the language (app_languages), and I know which one to select (language wise) because it's linked in the app_link_lang table.
Now I got the following query, but that is (obviously) not working..:
select f.form_id, f.name, b.name as beursnaam, l.name as languagename
FROM app_forms f, app_lang_link ll
WHERE f.id=1
LEFT JOIN app_beurzen b ON (b.form_id = f.id)
LEFT JOIN app_languages l ON ll.form_id = f.id
This should do the job:
SELECT e.name ename, f.id fid, f.name fname, l.name lname
FROM app_exhibition e
INNER JOIN app_forms f ON f.id=e.form_id
INNER JOIN app_link_lang al ON al.form_id=f.id
INNER JOIN app_languages l ON l.id=al.lang_id
You forgot to weave in the link table app_link_lang providing the m-to-n link. The result can now consist of several lines per exihibition, depending on the languages linked to it in app_link_lang.
Edit
I extended your fiddle (filled in some data) and it works, see here: http://sqlfiddle.com/#!9/a86be/1

Use inner join, left join or right join for join 2 tables

I'm realizing a project which raises me the next tables:
For being more specific: First table:
'docs' => doc_id, doc_type_type_id, clients_cli_id
where doc_type_type_id
invoices
reference guides
Second Table:
'client' => cli_id
What I try to do is to join Client with doc that My query is:
Show Client with his invoice and reference guide:
SELECT c.cli_name, d1.doc_file as f1 , d2.doc_file as f2 FROM clients c INNER JOIN docs d1 ON d1.client_cli_id = c.cli_id INNER JOIN docs d2 ON d2.client_cli_id = c.cli_id WHERE d1.doc_fec=d2.doc_fec
select * from docs
inner join client on docs.clients_cli_id = client.cli_id
where doc_type_type_id = 1
Something in this format should give you all invoices joined to client.

How to search where some data is in table 1 and other data is in table 3 with both having a UUID the same

I have 3 tables
For instance
Salestable
-ID
-variableB
-customerUUID
-variableC
Customertable
-customerUUID
-contractUUID
Contracttable
-contractUUID
-variableD
So I am currently doing a SQL Query on salestable
Like:
SELECT DISTINCT variableB FROM Salestable WHERE variableD = "blah";
How can I do this? Where I can find the contract associated with the current salestable?
A bit more info
They are all a 1:1 relationship - so Contracttable is tied to 1 Customertable which is tied to 1 salestable
There is a LOT of data in my database thousands of entries - this query does not run constantly but does need to run somewhat efficent.
SELECT a.*
FROM SalesTable a
INNER JOIN CustomerTable b
ON a.customerUUID = b.customerUUID
INNER JOIN Contracttable c
ON b.contractUUID = c.contractUUID
WHERE c.variableD = 'valueHere'
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
If you sure the contract exists use this (othewise swap INNER FOR LEFT):
SELECT variableB, variableD
FROM Salestable t1
INNER JOIN Customertable t2 ON (t1.customerUUID = t2.customerUUID)
INNER JOIN Contracttable t3 ON (t3.contractUUID = t2.contractUUID)
WHERE variableD = "blah"
GROUP BY t1.variableB

mysql select alias not working

Im having trouble with my select statement, when run title_two and author_two are not being filled properly by the next title value. Instead they print out the same as b.title and b.author. I've tried declaring them as
`B.title AS title_two`.
SELECT R.bookone, B.title, B.author,
R.booktwo, B.title title_two, B.author author_two,
R.relation, R.relationlike, R.relationdislike
FROM relationships R
INNER JOIN books B ON R.bookone = B.bookid;
there are two tables
relationships which has the following - relationshipid, bookone, booktwo, relation, relationlike, relationdislike
then books which is bookid, title, author, publisher
bookone and booktwo are foreign keys referencing bookid what im trying to acheive is have it so that when a user clicks a link itll come up with every relationship that book has with other books
Use Quotes while using alias
SELECT R.bookone, B.title, B.author,
R.booktwo, B.title as 'title_two', B.author as 'author_two',
R.relation, R.relationlike, R.relationdislike
FROM relationships R
INNER JOIN books B ON R.bookone = B.bookid;
You need to join on books one more time. Something like:
SELECT R.bookone, B1.title, B1.author,
R.booktwo, B2.title title_two, B2.author author_two,
R.relation, R.relationlike, R.relationdislike
FROM relationships R
INNER JOIN books B1 ON R.bookone = B1.bookid
INNER JOIN books B2 ON R.booktwo = B2.bookid
They are doing what they're supposed to do. author_two should be the same as B.author, and title_two should be the same as B.title. They are just aliases.
Also, asking for the same column twice from a single table won't get the next result in the table -- it just returns the same column twice.
If aliasing does not work in your queries, please check if you have included
useOldAliasMetadataBehavior=true
in JDBC connection string.
https://bugs.mysql.com/bug.php?id=33966
The correct format is: ColName as NewColName
SELECT R.bookone as `BookOne`
, ...
FROM relationships R
INNER JOIN books B ON R.bookone = B.bookid;
or simply ( without AS)
SELECT R.bookone `BookOne`
, ...
FROM relationships R
INNER JOIN books B ON R.bookone = B.bookid;

SQL: Get latest entries from history table

I have 3 tables
person (id, name)
area (id, number)
history (id, person_id, area_id, type, datetime)
In this tables I store the info which person had which area at a specific time. It is like a salesman travels in an area for a while and then he gets another area. He can also have multiple areas at a time.
history type = 'I' for CheckIn or 'O' for Checkout.
Example:
id person_id area_id type datetime
1 2 5 'O' '2011-12-01'
2 2 5 'I' '2011-12-31'
A person started traveling in area 5 at 2011-12-01 and gave it back on 2011-12-31.
Now I want to have a list of all the areas all persons have right now.
person1.name, area1.number, area2.number, area6.name
person2.name, area5.number, area9.number
....
The output could be like this too (it doesn't matter):
person1.name, area1.number
person1.name, area2.number
person1.name, area6.number
person2.name, area5.number
....
How can I do that?
This question is, indeed, quite tricky. You need a list of the entries in history where, for a given user and area, there is an 'O' record with no subsequent 'I' record. Working with just the history table, that translates to:
SELECT ho.person_id, ho.area_id, ho.type, MAX(ho.datetime)
FROM History AS ho
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
)
GROUP BY ho.person_id, ho.area_id, ho.type;
Then, since you're really only after the person's name and the area's number (though why the area number can't be the same as its ID I am not sure), you need to adapt slightly, joining with the extra two tables:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
);
The NOT EXISTS clause is a correlated sub-query; that tends to be inefficient. You might be able to recast it as a LEFT OUTER JOIN with appropriate join and filter conditions:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
LEFT OUTER JOIN History AS hi
ON hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
WHERE ho.type = 'O'
AND hi.person_id IS NULL;
All SQL unverified.
You're looking for results where each row may have a different number of columns? I think you may want to look into GROUP_CONCAT()
SELECT p.`id`, GROUP_CONCAT(a.`number`, ',') AS `areas` FROM `person` a LEFT JOIN `history` h ON h.`person_id` = p.`id` LEFT JOIN `area` a ON a.`id` = h.`area_id`
I haven't tested this query, but I have used group concat in similar ways before. Naturally, you will want to tailor this to fit your needs. Of course, group concat will return a string so it will require post processing to use the data.
EDIT I thikn your question has been edited since I began responding. My query does not really fit your request anymore...
Try this:
select *
from person p
inner join history h on h.person_id = p.id
left outer join history h2 on h2.person_id = p.id and h2.area_id = h.area_id and h2.type = 'O'
inner join areas on a.id = h.area_id
where h2.person_id is null and h.type = 'I'