Your last query
mysql> select table_name from tables as a left join (select distinct table_name from tables as b) on a.table_name!=b.table_name;
ERROR 1248 (42000): Every derived table must have its own alias
fails because the as b
must be outside the parentheses like this
mysql> select table_name from tables as a left join (select distinct table_name from tables) as b on a.table_name!=b.table_name;
Your method 2 failed
mysql> select count(table_name) as num, table_name from tables group by table_name where num > 1;
because the group by table_name
must be last like this
mysql> select count(table_name) as num, table_name from tables where num > 1 group by table_name;
SUGGESTION
Perhaps you should start with a GROUP BY ... HAVING
query like this
SELECT table_name,COUNT(1) table_count
FROM information_schema.tables
WHERE table_schema NOT IN
('information_schema','performance_schema','mysql')
GROUP BY table_name HAVING COUNT(1) > 1;
This will definitely give all tables whose name appears in multiple databases
Form that as a subquery and join it to gather all databases the table appears in
SELECT
A.table_name,
GROUP_CONCAT(B.table_schema) TheTableAppearsInTheseDatabases
FROM
(
SELECT table_name,COUNT(1) table_count
FROM information_schema.tables
WHERE table_schema NOT IN
('information_schema','performance_schema','mysql')
GROUP BY table_name HAVING COUNT(1) > 1
) A INNER JOIN information_schema.tables B
USING (table_name) GROUP BY A.table_name;
Please notice that I use INNER JOIN
rather than LEFT JOIN
because it will really form a Cartesian product (2704 X 2704) and then perform comparisons.
I know this works because I tried it out in MySQL 5.5.12 on my Windows7 machine
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 33
Server version: 5.5.12-log MySQL Community Server (GPL)
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SELECT
-> A.table_name,
-> GROUP_CONCAT(B.table_schema) TheTableAppearsInTheseDatabases
-> FROM
-> (
-> SELECT table_name,COUNT(1) table_count
-> FROM information_schema.tables
-> WHERE table_schema NOT IN
-> ('information_schema','performance_schema','mysql')
-> GROUP BY table_name HAVING COUNT(1) > 1
-> ) A INNER JOIN information_schema.tables B
-> USING (table_name) GROUP BY A.table_name;
+--------------------------+-------------------------------------------------------------------------------------------------------------------+
| table_name | TheTableAppearsInTheseDatabases |
+--------------------------+-------------------------------------------------------------------------------------------------------------------+
| a | junk,test,robottinosino |
| acl | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive |
| blocks | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| blog | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive |
| blog_category | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| blog_entrycat | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive |
| blog_meta | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_archive,weisci_jaws_staging2 |
| blog_trackback | weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging |
| calendar_events | weisci_jaws_staging,weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2 |
| calendar_meta | weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging |
| calendar_questions | weisci_jaws_staging,weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2 |
| calendar_tickets | weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging |
| calendar_transactions | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging,weisci_jaws_archive |
| captcha_complex | weisci_jaws_staging,weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2 |
| change_log | test,junk |
| chat_staff | test,junk |
| comments | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging,weisci_jaws_archive |
| donations_charities | weisci_jaws_staging,weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2 |
| donations_charities_meta | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| donations_donations | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| foo_reference1 | timpost1,timpost2 |
| foo_reference2 | timpost1,timpost2 |
| foo_reference3 | timpost1,timpost2 |
| groups | weisci_jaws_staging,weisci_jaws_archive,weisci_jaws_live,weisci_jaws_staging2 |
| ipvisitor | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| job_post | giannosfor,test |
| layout | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| listeners | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| mediamanager_files | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_staging |
| mediamanager_group | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| mediamanager_photos | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| mediamanager_video | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| menus | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| menus_groups | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| mytable | ryanzec,user1267617,cabita,dotancohen,johnlocke,neeraj,test,user391986,cool_cs,javier,mathieu |
| mytext | jakobud,newstuff |
| occupation_field | giannosfor,test |
| policy_agentblock | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| policy_ipblock | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| prova | veto,vito |
| registry | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| registry_bk | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| session | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| static_pages | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| static_pages_translation | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| t | preeti,rollup_test |
| t1 | abidibo,test |
| t2 | test,abidibo |
| t3 | test,abidibo |
| table1 | table_test,supercoolville,test |
| table2 | supercoolville,test,table_test |
| tags | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| tags_content | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| tbl_banner_position | weisci_jaws_staging2,weisci_jaws_live |
| tbl_banner_upload | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| tbl_global_banner | weisci_jaws_staging2,weisci_jaws_live |
| tms_authors | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| tms_repositories | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| tms_themes | weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging |
| updates | test,junk |
| url_aliases | weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2,weisci_jaws_archive |
| url_maps | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| users | weisci_jaws_archive,weisci_jaws_staging,giannosfor,veto,weisci_jaws_live,weisci_jaws_staging2,friends,sample,vito |
| users_groups | weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live,weisci_jaws_staging2 |
| users_meta | weisci_jaws_staging2,weisci_jaws_archive,weisci_jaws_staging,weisci_jaws_live |
+--------------------------+-------------------------------------------------------------------------------------------------------------------+
65 rows in set (0.91 sec)
mysql>
Give it a Try !!!
Best Answer
First, let's sum up a few assumptions:
item_code
is not a unique value initem
.shipment_unit
table is a simple list of all "unit" items in all shipment boxes;shipment_consumable
is (similarly) a list of all "consumables" in all shipment boxes.shipment_unit
andshipment_consumable
have noquantity
column of their own; so, if a given shipment box was supposed to have (say) 1 Windows phone and two wired headsets, you would have to have two rows inshipment_consumable
for the box, with the sameshipment_box_id
anditem_id
.shipment_box
, rather than the total items and quantities in the totalquantity
of theshipment_box
. That is to say, ifshipment_box.quantity
is 17, and the box contains 2 Windows phones, you want2
as the count, not34
(2 * 17).First - I must say that there appears to be absolutely no reason to have both
shipment_unit
andshipment_consumable
. The tables appear to have the exact same structure, and foreign keys to the exact same other tables (shipment_box
anditem
). You know whether a given item is consumable or a "unit" form the item table, so there's no good reason I can see to separate the two things from each other. I feel obligated to point this out, as I suspect your design would be much simpler with just one table (shipment_content
, perhaps).Similarly, having a
quantity
field for eachitem
in ashipment_unit
(or_consumable
, or_content
) seems like an obvious plus; barring different values fordate_added
, there's no good reason to have:in order to get two Windows phone in the same
shipment_box
. This may not seem likely at this point, but to me it seems like a trivially predictable need for the future. That said, some would say if you don't need it as part of the current plans, leave it out rather than cluttering your design with what could become a bunch of unused fields.That said, we don't always have the option to choose certain elements of the design - you may be stuck with this table layout, through no fault of you own.
So, if this is how it all works, and if it's how it must work, how do you get the info you need? I think your draft query would work accurately, and your
JOIN
query would not (except for degenerate cases, where there's 0 or 1 rows for a givenshipment_box_id
in each of the other two tables).As written, there's one potential issue with your
JOIN
query - it may not be relevant, but it should be noted. You are performing anINNER JOIN
to bothship_unit
andship_consumables
. If ashipment_box
only had "unit"-type items in it, then you would get back no data for it - because as written, there must be at least one "unit" and at least one consumable for ashipment_box
to be displayed.To avoid this, we should make the joins
LEFT JOIN
s, so we get ashipment_box
even if it's only got units or consumables, but not both (Note that by doing this, we'll also get ashipment_box
that has no items attached. If necessary, we can filter those out later.)The next thing to understand is how joins work. Each row in the underlying result set will have the fields from
shipment_unit
, and the fields fromshipment_consumable
. If you'll always have at most 1 row from each table, things will work as you expect; otherwise, they won't.Let's posit a
shipment_box
(shipment_box_id
= 5,box_code
= 'BX-255',quantity
= 10) with the following contents:So,
shipment_unit
has:and
shipment_consumable
has:If we join
shipment_box
,shipment_unit
, andshipment_consumable
as you indicate, we get the following (I've left out theshipment_box
columns, and theshipment_box_id
anddate_added
from the other two tables, for readability):Basically, since there's no criteria to tie records from
shipment_unit
andshipment_consumable
together, we get the cross-product of the records from each of those table that match our currentshipment-box
.When we go to match
item
rows to what weve already got, we see that each row will match two items - theshipment_unit
item, and theshipment_consumable
item. So, withitem_code
attached, we've got this:So, when we group by
item_code
there are two rows with 'ITM-002', and we'll get a count of 2 for that item (even though only one is in theshipment_box
).There are a couple of ways to work around this.
Since, as I noted above, there's really no reason to have separate
shipment_unit
andshipment_consumable
table, you can use a union of the two tables within your existing query, instead of getting theUNION
of two completely different queries:This way, in our example, the subquery would generate three rows - 1 from
shipment_unit
, and 2 fromshipment_consumable
.Of course, that solution still includes a
UNION
. So, if you don't like that, then we can ignore counting the items from our result set altogether, and make simple separate queries to get the counts:Note that we have to add
sb.shipment_box_id
to theGROUP BY
, since we're using that for theSELECT COUNT(*)
subqueries.This is making a number of allowances:
item_code
is not unique (for instance, if you haveitem_id
27 that's a unit, anditem_id
31 that's a consumable, but (since they're actually the same thing) both rows haveitem_code
'ITM-027')item_id
27 inshipment_unit
, ANDitem_id
31 inshipment_consumable
. Since it's counting the occurences in both tables regardless, it would correctly generate a count of 2 foritem_code
'ITM-027'If (as I would tend to assume) every
item_code
has one and only oneitem_id
, We can avoid the extraSELECT COUNT(*)
queries altogether.Here, we use
i.item_type' to determine what value to
COUNT, so we need that in the
GROUP BY`.We're back to basing our
COUNT
on our result set. As noted before, we could see our incidence of unit or consumable items multiplied through theJOIN
. However, we're not counting the rows directly; we're counting the number of distinct IDs fromshipment_unit
orshipment_consumable
. This factors those multiple rows right back out again, and we'll get correct counts.Finally, here's a DB-Fiddle link showing your two queries (tweaked slightly so the work), and my three, in action.
I'd recommend my 2nd query (
COUNT
via sub-queries) ifitem_code
is not unique, and my 3rd (COUNT DISTINCT
) is it is unique.