#1066 - Not unique table/alias: - mysql

Can you please help me out. I have this SQL query:
SELECT l.url
FROM (b INNER JOIN links ON b.parent_id = l.id)
INNER JOIN b ON l.id = b.link
WHERE l.url LIKE 'http://domain%' LIMIT 0, 30
And somehow it says
#1066 - Not unique table/alias: b

You seem to be selecting from the same table twice. Each of these occurrences needs its own alias:
SELECT
l.url
FROM
b as b1 /* <-- */
INNER JOIN links as l
ON b1.parent_id = l.id
INNER JOIN b as b2 /* <-- */
ON l.id = b2.link
WHERE l.url LIKE 'http://domain%' LIMIT 0, 30
Please note that I also added the missing alias l for the links table.

SELECT l.url from b inner join links as l on l.id = l.parent_id
inner join b as b1 on b1.link = l.id
where l.url like 'http:domain%' limit 0,30
In this query we r join two table first b and second links and self join b as b1 alias ok

Related

MySQL with ON condition from another table

Let's say that I have:
SELECT * FROM a
LEFT OUTER JOIN b ON b.a_id = a.id
LEFT OUTER JOIN c ON b.c_id = c.id
Now what I want to do is to select b's that are assigned to c that is e. g. active (c.active = 1). How can I do that with ON?
Note that I can't use WHERE after the whole query above, because I want a's to be returned even if 0 b's are found.
Just to make sure, I understood the question: You want all rows where either c.active equals 1 or where there is no entry in b or c, right?
It's a bit lengthy but this seems to work:
SELECT * FROM a
LEFT OUTER JOIN b ON a.aid = b.aid
LEFT OUTER JOIN c ON b.bid = c.bid
WHERE a.aid NOT IN (
SELECT a.aid FROM a
INNER JOIN b ON a.aid = b.aid
INNER JOIN c ON b.bid = c.bid
WHERE NOT c.active
);
I could also imagine a solution using UNION
Which rows are returned in each case... Note that one case is different:
FROM b JOIN c ON ... AND c.active=1 -- rows in both tables exist and active
FROM b JOIN c ON ... WHERE c.active=1 -- ditto
FROM b LEFT JOIN c ON ... WHERE c.active=1 -- ditto
FROM b LEFT JOIN c ON ... AND c.active=1 -- all b's, but NULLs for inactive/missing c's
(Caveat: I am not sure I got the cases correct; just keep in mind that ON and WHERE are not always interchangeable.)
When mixing JOIN and LEFT JOIN, you may need to add parentheses:
FROM a JOIN ( b LEFT JOIN c ON... ) ON ... WHERE ...
FROM ( a JOIN b ON ... ) LEFT JOIN c ON... WHERE ...

Query with several consecutive LEFT JOIN - unexpected results

My goal is to populate several objects of several child classes (B, C, D, E, F...), all extending a parent class which is A. All of this, in one single and only big query.
Let's say I have several tables reflecting the classes structure, including these 3 ones:
Table A /* the parent class */
id type created
--------------------------------
392 B 1377084886
Table B /* one of the child classes */
id myfield myotherfield anotherone oneagain
-------------------------------------------------------------
392 234 'foo' 'bar' 3
Table G /* not part of the structure, just here for the query to check a field */
myfield fieldtocheck evenmorefields
------------------------------------------------
234 'myvalue1' 'foobar'
Now:
/* This (the query I want): */
SELECT
a.*,
b.*,
c.*,
d.*,
e.*,
f.*
FROM A a
LEFT JOIN B b ON a.id = b.id
LEFT JOIN C c ON a.id = c.id
LEFT JOIN D d ON a.id = d.id
LEFT JOIN E e ON a.id = e.id
LEFT JOIN F f ON a.id = f.id
LEFT JOIN G g_b ON b.myfield = g_b.myfield
LEFT JOIN G g_c ON c.myfield = g_c.myfield
WHERE g_b.fieldtocheck IN (myvalue1);
/* Returns this (what I don't want): */
id->392
type->B
created->1377084886
myfield->NULL /* why NULL? */
myotherfield->NULL /* why NULL? */
anotherone->NULL /* why NULL? */
oneagain->3 /* why, whereas other fields from B are NULL, is this one correctly filled? */
Whereas:
/* This (the query I don't want): */
SELECT
a.*,
b.*
FROM A a
LEFT JOIN B b ON a.id = b.id
LEFT JOIN G g_b ON b.myfield = g_b.myfield
WHERE g_b.fieldtocheck IN (myvalue1);
/* Returns this (what I want): */
id->392
type->B
created->1377084886
myfield->234
myotherfield->'foo'
anotherone->'bar'
oneagain->3
I have no idea why. Tried different things, but this is what I come up with. Has someone an idea?
EDIT: Clarified this post and made it more straightforward.
I think the problem that you are facing is the collision of names in the query. That is, there are multiple columns with the same name and MySQL chooses one of them for the result.
You need to alias the column names for each of the tables to a different name, for example, a_created, b_created, etc.
This appears to be the classic case where you need to move your where into the join itself so that it doesn't block everything else:
SELECT
A.*,
B.*,
C.*,
D.*,
E.*,
F.*,
FROM A
LEFT JOIN B ON A.id = B.id
LEFT JOIN C ON A.id = C.id
LEFT JOIN D ON A.id = D.id
LEFT JOIN E ON A.id = E.id
LEFT JOIN F ON A.id = F.id
LEFT JOIN G ON B.myfield = G.myfield and G.anotherfield IN (myvalue1)
LEFT JOIN H ON C.myfield = H.myfield;
SELECT a.id, a.type, a.created, b.myfield, b.myotherfield FROM `A` AS a INNER JOIN `B` AS b ON a.id = b.id ;
Use this It must work fine. If you have an additional where query you can add it.

Rows missing from mysql pivot query results

I have a mysql query as stated below, it returns exactly the results I want for one row, but doesn't return any other rows where I expect there to be 8 in my test data (there are 8 unique test ids). I was inspired by this answer but obviously messed up my implementation, does anyone see where I'm going wrong?
SELECT
c.first_name,
c.last_name,
n.test_name,
e.doc_name,
e.email,
e.lab_id,
a.test_id,
a.date_req,
a.date_approved,
a.accepts_terms,
a.res_value,
a.reason,
a.test_type,
a.date_collected,
a.date_received,
k.kind_name,
sum(case when metabolite_name = "Creatinine" then t.res_val end) as Creatinine,
sum(case when metabolite_name = "Glucose" then t.res_val end) as Glucose,
sum(case when metabolite_name = "pH" then t.res_val end) as pH
FROM test_requisitions AS a
INNER JOIN personal_info AS c ON (a.user_id = c.user_id)
INNER JOIN test_types AS d ON (a.test_type = d.test_type)
INNER JOIN kinds AS k ON (k.id = d.kind_id)
INNER JOIN test_names AS n ON (d.name_id = n.id)
INNER JOIN docs AS e ON (a.doc_id = e.id)
INNER JOIN test_metabolites AS t ON (t.test_id = a.test_id)
RIGHT JOIN metabolites AS m ON (m.id = t.metabolite_id)
GROUP BY a.test_id
ORDER BY (a.date_approved IS NOT NULL),(a.res_value IS NOT NULL), a.date_req, c.last_name ASC;
Most of your joins are inner joins. The last is a right outer join. As written, the query keeps all the metabolites, but not necessarily all the tests.
I would suggest that you change them all to left outer joins, because you want to keep all the rows in the first table:
FROM test_requisitions AS a
LEFT JOIN personal_info AS c ON (a.user_id = c.user_id)
LEFT JOIN test_types AS d ON (a.test_type = d.test_type)
LEFT JOIN kinds AS k ON (k.id = d.kind_id)
LEFT JOIN test_names AS n ON (d.name_id = n.id)
LEFT JOIN docs AS e ON (a.doc_id = e.id)
LEFT JOIN test_metabolites AS t ON (t.test_id = a.test_id)
LEFT JOIN metabolites AS m ON (m.id = t.metabolite_id)
I would also suggest that your aliases be related to the table, so tr for test_requisition, pi for personal_info, and so on.

MYSQL JOINS with 3 tables

TABLE A, B, C
How can I make a query that joins these three tables. The condition is that Table A must have a record.
I tried like this
select * from a
left join b on a.article_id = b.article_id
left join c on b.file_id = c.submission_id
where c.user_id = 6;
My query doesn't work in the case that Table C is missing a record. In that case, the join doesn't work for the three tables.
Any criteria on the outer tables must be int he relevant ON clause, not the WHERE clause.
For example:
select * from a
left join b on a.article_id = b.article_id
left join c on b.file_id = c.submission_id and c.user_id = 6;
If you use LEFT JOIN, then records from a and b are selected even if there are no corresponding records in table c. Use INNER JOIN instead:
SELECT * FROM a
INNER JOIN b ON a.article_id = b.article_id
INNER JOIN c ON b.file_id = c.submission_id
WHERE c.user_id = 6;

MySQL GROUP BY performance issue

This is the query I'm performing (without some Joins that are not relevant):
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
GROUP BY a.id
Each row of "a" is linked with 1 to 5 rows in "b".
The problem is that GROUP BY has performance issues (it takes 10x or more using GROUP BY than not using it). I need to retrieve only one row of each member in "a".
How can I make this faster?
edit: I need to be able to filter by a.id AND/OR c.id. The resultset I should be getting is only 1 row per "valid" member of "a", meaning the rows that match the constraints. Rows that don't match the filters shouldn't be returned.
In my original query, this would be done this way:
SELECT a.*, c.id
FROM a
LEFT OUTER JOIN b ON a.id = b.id_anunciante
LEFT OUTER JOIN c ON c.id = b.id_rubro
WHERE c.id = 1
OR a.id = 1
GROUP BY a.id
a.id, b.id_anunciante, b.id_rubro, c.id are all indexes.
SELECT a.*,
(
SELECT c.id
FROM b
JOIN с
ON c.id = b.id_rubro
WHERE b.id_anunciante = a.id
-- add the ORDER BY condition to define which row will be selected.
LIMIT 1
)
FROM a
Create the index on b (id_anunciante) for this to work faster.
Update:
You don't need the OUTER JOINs here.
Rewrite your query as this:
SELECT a.*, c.id
FROM a
JOIN b
ON b.id_anunciante = a.id
JOIN c
ON c.id = b.id_rubro
WHERE a.id = 1
UNION ALL
SELECT a.*, 1
FROM a
WHERE EXISTS
(
SELECT NULL
FROM c
JOIN b
ON b.id_rubro = c.id
WHERE c.id = 1
AND b.id_anunciante = a.id
)
Add ORDER BY NULL to avoid the implicit sorting MySQL does when doing a group by.
I suppose you have indexes/PKs on a.id, b.id_anunciante, b.id_rubro and c.id ? I guess you could try adding a composite index on (b.id_anunciante, b.id_rubro) if your mysql version is not able to do an index merge.