Error # 1066 - not a unique table / alias in MySQL - mysql

Good afternoon, I’m trying to fulfill the request while writing an error. Error # 1066 does not quite understand how it can be fixed in my particular case. Perhaps the problem is that I connect to the table several times and need an alias.
SELECT `employees`.`name`, `employees`.`surname`, `employees`.`patronymic`,
`doc`.`name`, `doc`.`agreement`, `tank`.`name`,
`liquid`.`name`, `WorkPlan`.`description`
FROM `WorkPlan` , `employees` , `doc` , `tank` , `liquid`
LEFT JOIN `WorkPlan` ON `tank`.`id` = `WorkPlan`.`id_tank`
LEFT JOIN `WorkPlan` ON `liquid`.`id` = `WorkPlan`.`id_liquid`
LEFT JOIN `WorkPlan` ON `doc`.`id` = `WorkPlan`.`id_doc`
AND `WorkPlan`.`id_tank` = `tank`.`id`
AND `WorkPlan`.`id_liquid` = `liquid`.`id`
AND `WorkPlan`.`id_doc` = `doc`.`id`

I suspect (by your SELECT list of columns) that you want to join employees to the other tables.
For every join you must specify in the ON clause the columns that relate the 2 tables and it is a good practice to use aliases for the tables which shorten the code and make it more readable:
SELECT e.name, e.surname, e.patronymic,
d.name, d.agreement,
t.name,
l.name,
w.description
FROM employees e
LEFT JOIN WorkPlan w ON e.? = w.?
LEFT JOIN tank t ON t.id = w.id_tank
LEFT JOIN liquid l ON l.id = w.id_liquid
LEFT JOIN doc d ON d.id = w.id_doc
Replace the ? with the names of the columns that relate employees with WorkPlan.

Related

SQL query optimization for speed

So I was working on the problem of optimizing the following query I have already optimized this to the fullest from my side can this be further optimized?
select distinct name ad_type
from dim_ad_type x where exists ( select 1
from sum_adserver_dimensions sum
left join dim_ad_tag_map on dim_ad_tag_map.id=sum.ad_tag_map_id and dim_ad_tag_map.client_id=sum.client_id
left join dim_site on dim_site.id = dim_ad_tag_map.site_id
left join dim_geo on dim_geo.id = sum.geo_id
left join dim_region on dim_region.id=dim_geo.region_id
left join dim_device_category on dim_device_category.id=sum.device_category_id
left join dim_ad_unit on dim_ad_unit.id=dim_ad_tag_map.ad_unit_id
left join dim_monetization_channel on dim_monetization_channel.id=dim_ad_tag_map.monetization_channel_id
left join dim_os on dim_os.id = sum.os_id
left join dim_ad_type on dim_ad_type.id = dim_ad_tag_map.ad_type_id
left join dim_integration_type on dim_integration_type.id = dim_ad_tag_map.integration_type_id
where sum.client_id = 50
and dim_ad_type.id=x.id
)
order by 1
Your query although joined ok, is an overall bloat. You are using the dim_ad_type table on the outside, just to make sure it exists on the inside as well. You have all those left-joins that have NO bearing on the final outcome, why are they even there. I would simplify by reversing the logic. By tracing your INNER query for the same dim_ad_type table, I find the following is the direct line. sum -> dim_ad_tag_map -> dim_ad_type. Just run that.
select distinct
dat.name Ad_Type
from
sum_adserver_dimensions sum
join dim_ad_tag_map tm
on sum.ad_tag_map_id = tm.id
and sum.client_id = tm.client_id
join dim_ad_type dat
on tm.ad_type_id = dat.id
where
sum.client_id = 50
order by
1
Your query was running ALL dim_ad_types, then finding all the sums just to find those that matched. Run it direct starting with the one client, then direct with JOINs.

PHP MySQL: Join 3 tables but

I have 3 tables, errorcode_table, description_table, and customer_table.
The query below will display all records that are in the errorcode_table and I have an inner join that will also display the customer_table as per the serial number in both tables.
SELECT
errorcode_table.error,
errorcode_table.deviceserialnumber,
customer_table.serialnumber,
customer_table.customer,
FROM errorcode_table
INNER JOIN customer_table
ON errorcode_alert_table.deviceserialnumber = customerinfo_table.serialnumber
Now I want to also display the description of the error code as well, here's my attempt:
SELECT
errorcode_table.error,
errorcode_table.serialnumber,
customer_table.serialnumber,
customer_table.customer,
description.serialnumber
description.info
FROM errorcode_table
INNER JOIN customer_table
RIGHT JOIN description_table
ON errorcode_table.deviceserialnumber = customer_table.serialnumber
ON errorcode_table.deviceserialnumber = description_table.serialnumber
Now I'm not getting any records. Please assist.
The ON clause for each join should appear immediately after each join condition. And you can introduce table aliases to make the query easier to read.
SELECT
e.error,
e.serialnumber,
c.serialnumber,
c.customer,
d.serialnumber,
d.info
FROM errorcode_table e
INNER JOIN customer_table c
ON e.deviceserialnumber = c.serialnumber
RIGHT JOIN description_table d
ON e.deviceserialnumber = d.serialnumber;

How can I merge these two left joins into a single one?

How can I merge these two left joins: http://sqlfiddle.com/#!9/1d2954/69/0
SELECT d.`id`, (adcount + bdcount)
FROM `docs` d
LEFT JOIN
(
SELECT da.`doc_id`, COUNT(da.`doc_id`) AS adcount FROM `docs_scod_a` da
INNER JOIN `scod_a` a ON a.`id` = da.`scod_a_id`
WHERE a.`ver_a` IN ('AA', 'AB')
GROUP BY da.`doc_id`
) ad ON ad.`doc_id` = d.`id`
LEFT JOIN
(
SELECT db.`doc_id`, COUNT(db.`doc_id`) AS bdcount FROM `docs_scod_b` db
INNER JOIN `scod_b` b ON b.`id` = db.`scod_b_id`
WHERE b.`ver_b` IN ('BA', 'BB')
GROUP BY db.`doc_id`
) bd ON bd.`doc_id` = d.`id`
to be a Single left join just to ease its use in my code, while making it no less slower?
Let me first emphasize that your method of doing the calculation is the better method. You have two separate dimensions and aggregating them separately is often the most efficient method for doing the calculation. It is also the most scalable method.
That said, your query should be equivalent to this version:
SELECT d.id,
count(distinct a.id),
count(distinct b.id)
FROM docs d left join
docs_scod_a da
ON da.doc_id = d.id LEFT JOIN
scod_a a
ON a.id = da.scod_a_id AND a.ver_a IN ('AA', 'AB') LEFT JOIN
docs_scod_b db
ON db.doc_id = d.id LEFT JOIN
scod_b b
ON b.id = db.scod_b_id AND b.ver_b IN ('BA', 'BB')
GROUP BY d.id
ORDER BY d.id;
This query is more expensive than it looks, because the COUNT(DISTINCT) incurs additional overhead compared to COUNT().
And here is the SQL Fiddle.
And, because LEFT JOIN can return NULL values, your query is more correctly written as:
SELECT d.`id`, COALESCE(adcount, 0) + COALESCE(bdcount, 0)
If you were having problems with the results, this small change might fix those problems.
Performance may be a big problem, depending on sizes of each table. It appears to be an "inflate-deflate" situation since it first "inflates" the number of rows via JOIN, then "deflates" via GROUP BY. The formulation below avoids inflation-deflation.
But first, if I understand this subquery correctly, this
SELECT da.`doc_id`, COUNT(da.`doc_id`) AS adcount
FROM `docs_scod_a` da
INNER JOIN `scod_a` a ON a.`id` = da.`scod_a_id`
WHERE a.`ver_a` IN ('AA', 'AB')
GROUP BY da.`doc_id`
can be rewritten as
SELECT `doc_id`,
( SELECT COUNT(*)
FROM `scod_a`
WHERE `id` = da.`scod_a_id`
AND `ver_a` IN ('AA', 'AB')
) AS adcount
FROM `docs_scod_a` AS da
If that is correct, then the entire query becomes
SELECT d.id,
( SELECT COUNT(*)
FROM docs_scod_a ds
JOIN scod_a s ON s.id = ds.scod_a_id
WHERE ds.doc_id = d.id
AND s.ver_a IN ('AA', 'AB')
) +
( SELECT COUNT(*)
FROM docs_scod_b ds
JOIN scod_b s ON s.id = ds.scod_b_id
WHERE ds.doc_id = d.id
AND s.ver_b IN ('BA', 'BB')
)
FROM docs AS d
Which needs these indexes:
docs_scod_a: (doc_id, scod_a_id), (scod_a_id, doc_id)
docs_scod_b: (doc_id, scod_b_id), (scod_b_id, doc_id)
scod_a: (ver_a, id)
scod_b: (ver_b, id)
docs: -- presumably has PRIMARY KEY(id)
Note the lack of GROUP BY.
docs_scod_a smells like a many-to-many mapping table. I recommend you follow the tips here.
(No COALESCE is needed since COUNT will simply return zero.)
(I don't know whether my version is better (faster or whatever) than Gordon's, nor whether my indexes will help his formulation.)

SQL Join with Value Missing in One Column

I'm trying to create a SQL query that uses one table to count the number of blade servers our company has in each chassis and groups those, while joining it with chassis information from another table.
However, one of the chassis has no blades in it, so the name does not appear in the blade inventory table. Using an INNER JOIN creates a table that doesn't contain that blade in any capacity. A LEFT JOIN achieves the same effect, but a RIGHT JOIN gives me an extra row with a null value for the chassis name.
I'm guessing this is because the non-existence of that blade name in the first table is being given precedence over the second, but not sure how to correct that. My query, as of now, looks like this:
SELECT e.EnclosureName, e.PDUName, q.Blades, r.Serial#
FROM bladeinventory.table e JOIN
(
SELECT EnclosureName,COUNT(*) Blades
FROM bladeinventory.table
GROUP BY EnclosureName
) q ON e.EnclosureName = q.EnclosureName
LEFT JOIN chassisinventory.table r
ON e.EnclosureName = r.EnclosureName
GROUP BY e.EnclosureName, e.PDUName, q.Blades, r.Serial#
Is it possible to edit this in such a way that the name of the chassis with 0 blades is actually generated by the query?
Just pull the name from the chassisinventory table. I'll use coalesce(), just in case you switch the order of the joins (again):
SELECT COALESCE(r.EncloseName, e.EnclosureName) as EnclosureName, e.PDUName, q.Blades, r.Serial#
FROM bladeinventory.table e JOIN
(SELECT EnclosureName,COUNT(*) Blades
FROM bladeinventory.table
GROUP BY EnclosureName
) q
ON e.EnclosureName = q.EnclosureName LEFT JOIN
chassisinventory.table r
ON e.EnclosureName = r.EnclosureName
GROUP BY COALESCE(r.EncloseName, e.EnclosureName), e.PDUName, q.Blades, r.Serial#;
You can also use below code where case is being used which is much simpler and effective
SELECT e.EnclosureName, r.PDUName,
case when q.Blades IS NULL then 0
else q.Blades end Blades,
e.Serial#
FROM chassisinventory.table e
LEFT OUTER JOIN bladeinventory.table r on e.EnclosureName = r.EnclosureName
LEFT OUTER JOIN (SELECT EnclosureName,COUNT(*) Blades
FROM bladeinventory.table
GROUP BY EnclosureName
) q on e.EnclosureName = q.EnclosureName

selecting from multiple tables vs JOIN

I need to display all fixtures(who plays 'against' who) for a current user so I wrote SQL query
SELECT
fixture.*
FROM
sport_team_player AS team_player, sport_team AS team
INNER JOIN sport_fixture AS fixture
ON (`team_player`.`team_id` = fixture.`team1_id` OR `team_player`.`team_id` = fixture.`team2_id`)
WHERE
team_player.`team_id` = team.`team_id` AND team_player.`player_id` = '16'
And this doesn't work and tells me that team_player.team_id does not exist
but if I join the second table instead of selecting from multiple tables it works just fine.
PS. This is not the best way to write such query but it's generated by ORM module..
EDIT:
Result would be list of fixture data like
------------------------------
|fixture_id|team1_id|team2_id|
------------------------------
|1 | 2 | 3 |
------------------------------
Try this one. Should result to the same query as yours;
SELECT fixture.*
FROM sport_team_player AS team_player
JOIN sport_team AS team
ON team_player.`team_id` = team.`team_id` AND team_player.`player_id` = '16'
INNER JOIN sport_fixture AS fixture
ON (`team_player`.`team_id` = fixture.`team1_id`
OR `team_player`.`team_id` = fixture.`team2_id`)
You shouldn't mix up both notations when building up joins. The comma you are using to join team_player and team , and the subsequent calls to inner join, will most probably trigger unknown column error.
Precedence of the comma operator is less than of INNER JOIN, CROSS JOIN, LEFT JOIN. That's why when you mix comma with other join table operators [Unknown column 'col_name' in 'on clause'] error occur. Same query will work if you specify the cross join ( to get a Cartesian product of the first two tables) instead of commas, because then in the from clause the table operators will be evaluated from left to right:
SELECT
fixture.*
FROM
sport_team_player AS team_player
cross join sport_team AS team
INNER JOIN sport_fixture AS fixture
ON (team_player.team_id = fixture.team1_id OR team_player.team_id = fixture.team2_id)
WHERE
team_player.team_id = team.team_id AND team_player.player_id = '16'
E.g.:
SELECT f.*
FROM sport_team_player p
JOIN sport_team t
ON t.team_id = p.team_id
JOIN sport_fixture f
ON p.team_id IN(f.team1_id,f.team2_id)
WHERE p.player_id = 16;