SQL cross searching two tables - mysql

I have the following 2 tables..
mysql> describe catalog_category_reference;
+----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | text | NO | | NULL | |
| class_id | text | NO | | NULL | |
+----------+---------+------+-----+---------+----------------+
and
mysql> describe product_import_queue;
+-----------------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| unique_id | text | NO | | NULL | |
| category_code | text | NO | | NULL | |
| item_code | text | NO | | NULL | |
| ffl_flag | int(11) | NO | | NULL | |
| name | text | NO | | NULL | |
| price | text | NO | | NULL | |
| image | text | NO | | NULL | |
| custom_options_flag | int(11) | NO | | NULL | |
| custom_options_string | text | NO | | NULL | |
| short_desc | text | NO | | NULL | |
| long_desc | text | NO | | NULL | |
| process_status | int(11) | NO | | 0 | |
+-----------------------+---------+------+-----+---------+----------------+
I want to search through product_import_queue and find the "category_code"'s that do not exist in the catalog_Category_reference. Please note that, the category_code is stored in the catalog_reference table under class_id. Can I do this in one query? I've attempted something like...
SELECT category_code FROM product_import_queue
LEFT JOIN catalog_category_reference ON product_import_queue.category_code = catalog_category_reference.class_id;
But thats not what I'm looking for and I don't fully understand JOIN's yet.

You were almost there...just need to add a where clause...
SELECT category_code
FROM product_import_queue
LEFT JOIN catalog_category_reference
ON product_import_queue.category_code =
catalog_category_reference.class_id
WHERE catalog_category_reference.class_id IS NULL

SELECT category_code FROM product_import_queue
LEFT JOIN catalog_category_reference ON product_import_queue.category_code = catalog_category_reference.class_id
WHERE catalog_category_reference.class_id is null

SELECT category_code FROM product_import_queue LEFT JOIN catalog_category_reference ON product_import_queue.category_code = catalog_category_reference.class_id WHERE catalog_category_reference.class_id IS NULL
This query will find only products in queque which category_code isn't in category reference

Related

Write a mysql not in query as join

I have two tables vtiger_crmentity and vtiger_crmentityrel (from open source project vtiger).
vtiger_crmentity
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| crmid | int(19) | NO | PRI | NULL | |
| smcreatorid | int(19) | NO | MUL | 0 | |
| smownerid | int(19) | NO | MUL | 0 | |
| modifiedby | int(19) | NO | MUL | 0 | |
| setype | varchar(30) | NO | | NULL | |
| description | text | YES | | NULL | |
| createdtime | datetime | NO | | NULL | |
| modifiedtime | datetime | NO | | NULL | |
| viewedtime | datetime | YES | | NULL | |
| status | varchar(50) | YES | | NULL | |
| version | int(19) | NO | | 0 | |
| presence | int(1) | YES | | 1 | |
| deleted | int(1) | NO | MUL | 0 | |
| label | varchar(255) | YES | MUL | NULL | |
+--------------+--------------+------+-----+---------+-------+
vtiger_crmentityrel
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| crmid | int(11) | NO | | NULL | |
| module | varchar(100) | NO | | NULL | |
| relcrmid | int(11) | NO | | NULL | |
| relmodule | varchar(100) | NO | | NULL | |
+-----------+--------------+------+-----+---------+-------+
I am trying to get a list of contacts which are not present in the crmentityrel table (in the relcrmid column to be specific). I can do this via a subquery but it is taking about 2 minutes to complete (for about 20k records in each table).
I tried to convert the query to a join but i am surely doing something wrong as i keep getting wrong values (compared to the subquery which i know is right).
Any help is greatly appreciated. Please tell me if you need any details from my side
Edit -
My working query (with subquery) is -
SELECT crmid, label from vtiger_crmentity
WHERE deleted = 0 and setype="Contacts"
and crmid not in (select relcrmid from vtiger_crmentityrel
where relmodule="Contacts")
To convert a not in to a join, the idea is to use left join and where:
SELECT c.crmid, c.label
FROM vtiger_crmentity c left join
vtiger_crmentityrel cr
on c.crmid = cr.relcrmid and relmodule = 'Contacts'
WHERE c.deleted = 0 and c.setype = 'Contacts' and cr.relcrmid is null;
I should point out that the above is not exactly equivalent. NOT IN returns no rows if the subquery returns even a single NULL value. The above behaves more intuitively.
Because of the behavior of NOT IN with NULL values, NOT EXISTS is a better choice. Plus, it often has better performance as well:
SELECT crmid, label
FROM vtiger_crmentity c
WHERE deleted = 0 and setype = 'Contacts' AND
NOT EXISTS (SELECT relcrmid
FROM vtiger_crmentityrel cr
WHERE cr.relmodule = 'Contacts' and cr.relcrmid = c.crmid
);

Subquery as another field

I have trying to do a SELECT query....not an UPDATE or INSERT or DELETE.
I have three tables.
The customers table
The invoices table
The invoice_items table
I want to run a query that will show me every invoice. Each invoice can have only ONE customer and MANY items...hence the existence of invoice_items
My current query looks like this
SELECT i.order_date, c.name, thedata.info from invoices i inner join customers c ON (i.customer = c.id) right join ( select x.order, group_concat( concat(x.itemname,' ', x.itemdesc) separator "\n" ) as info from invoice_items x ) thedata on (i.id = thedata.order)
When I run this query, I receive one row that contains, one customer, one invoice, and a list of any an every item regardless of invoice id or customer...???
+---------------------+--------------+---------------------------------------------------------------------------------------------------------------------------------+
| order_date | name | info |
+---------------------+--------------+---------------------------------------------------------------------------------------------------------------------------------+
| 2014-01-23 20:39:20 | Joe Customer | Boxes for boxing
Shoes for shining
2" Hermosa Plank for bobblin
Boxes for boxing
bobbles for bobblin
Lot 297 Woodale Carmel Oak |
+---------------------+--------------+---------------------------------------------------------------------------------------------------------------------------------+
My goal is to receive this same list but show all customers along with THEIR items.
What am I doing wrong?
Here are the schemas, for those that need them.
Customers
+---------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | text | NO | | NULL | |
| ship_address | text | NO | | NULL | |
| ship_address2 | text | NO | | NULL | |
| ship_city | text | NO | | NULL | |
| ship_state | text | NO | | NULL | |
| ship_zip | int(6) | NO | | NULL | |
| bill_address | text | NO | | NULL | |
| bill_address2 | text | NO | | NULL | |
| bill_city | text | NO | | NULL | |
| bill_state | text | NO | | NULL | |
| bill_zip | text | NO | | NULL | |
| phone | bigint(20) | NO | | NULL | |
| email | text | NO | | NULL | |
+---------------+------------+------+-----+---------+----------------+
Invoices
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| customer | int(11) | NO | | NULL | |
| order_date | datetime | NO | | NULL | |
| status | text | NO | | NULL | |
| freightcost | double | NO | | NULL | |
+-------------+----------+------+-----+---------+----------------+
Invoice_items
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| order | int(11) | NO | | NULL | |
| qty | int(11) | NO | | NULL | |
| itemname | text | NO | | NULL | |
| itemdesc | text | NO | | NULL | |
| itemprice | double | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
try the below query, you need to use GROUP BY if you use GROUP_CONCAT().
SELECT i.order_date,
c.name,
group_concat( concat(x.itemname,' ', x.itemdesc) separator "\n" ) as info
FROM invoices i
INNER JOIN customers c ON i.customer = c.id
LEFT JOIN invoice_items x ON i.id = x.order
GROUP BY i.order_date,c.name

sql joining three tables using inner joins

in my database I have 3 tables named items, manufacturers and items_manufacturers. manufacturers has a HAS:MANY relation with items_manufacturers
My items table
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| code | varchar(25) | NO | MUL | NULL | |
| item_category | varchar(100) | NO | | NULL | |
| item_desc | varchar(500) | NO | | NULL | |
| reorder_point | int(11) | NO | | NULL | |
| unit | varchar(45) | NO | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
My manufacturers table
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| code | varchar(25) | NO | | NULL | |
| name | varchar(250) | NO | | NULL | |
| address | varchar(750) | NO | | NULL | |
| contact_no | varchar(50) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
My items_manufacturers table
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| item_id | bigint(20) | NO | MUL | NULL | |
| manufacturer_id | bigint(20) | NO | MUL | NULL | |
| unit_cost | decimal(20,2) | NO | | NULL | |
| vendor_id | bigint(20) | NO | | NULL | |
+-----------------+---------------+------+-----+---------+----------------+
In my result table I want items_id, items_desc, name of manufacturer from manufacturers table and manufacturer_id. The relation I have is
items.id=items_manufacturers.item_id and
manufacturers.id=items_manufacturers.manufacturer_id.
I tried using inner joins for three tables but not working.
The query I tried
select
items_manufacturers.id,
items.item_desc,
item_manufacturers.manufacturer_id,
manufacturer.name
from items_manufacturers
INNER JOIN items ON items_manufacturers.item_id=items.id
INNER JOIN manufacturers ON items_manufacturers.manufacturer_id=manufacturers.id
Anybody kindly help me with this, I am stuck up from a long time
I used this following code and got the result you were trying to get. This code may solve your problem:
select a.name,b.manufacturer_id,c.id,c.item_desc
from manufacturers as a
inner join
item_manufacturers as b
on b.manufacturer_id=a.id
inner join item as c
on c.id=b.item_id

MySQL db join query

I am working with an Employee database in Mysql. My Db contains the following tables
mysql> describe edept;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| dept | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
mysql>describe esal;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| basic | int(11) | NO | | NULL | |
| pf | int(11) | NO | | NULL | |
+-------+---------+------+-----+---------+-------+
mysql> describe edesig;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| desig | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
mysql> select * from edetails inner join edept on edetails.dept=edept.id;
+----+--------+-----+------+-------+-------+----+----+------------------+
| id | name | age | dept | desig | basic | pf | id | dept |
+----+--------+-----+------+-------+-------+----+----+------------------+
| 1 | swetha | 21 | 3 | 2 | 2 | 2 | 3 | Business Process |
+----+--------+-----+------+-------+-------+----+----+------------------+
mysql> describe edetails;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| dept | int(11) | NO | MUL | NULL | |
| desig | int(11) | YES | MUL | NULL | |
| basic | int(11) | NO | MUL | NULL | |
| pf | int(11) | NO | MUL | NULL | |
+-------+-------------+------+-----+---------+-------+
I have to get values for dept,desig,basic,pf from the tables edept.dept,edesig.desig,esal.basic,esal.pf respectively.
I used foreign keys for all the fields for which i have to retrieve values from other tables.And i tried a sample inner join query. but i got the output as follows:
mysql> select * from edetails inner join edept on edetails.dept=edept.id;
+----+--------+-----+------+-------+-------+----+----+------------------+
| id | name | age | dept | desig | basic | pf | id | dept |
+----+--------+-----+------+-------+-------+----+----+------------------+
| 1 | swetha | 21 | 3 | 2 | 2 | 2 | 3 | Business Process |
+----+--------+-----+------+-------+-------+----+----+------------------+
My edept table contains the following:
mysql> select * from edept;
+----+------------------+
| id | dept |
+----+------------------+
| 3 | Business Process |
+----+------------------+
How can i eliminate duplicate columns. i need the value "business process" in the dept field of the edept table
Try this::
select
edetails.id,
edetails.name,
edetails.age,
edetails.dept,
edesig.desig,
edetails.basic,
edetails.pf,
edept.dept
from edetails
inner join edept on edetails.dept=edept.id
INNER JOIN edesig on edesig.id=edetails.desig

Mysql Join Query optimisation

Hello i am trying to run this select statement using this query and it is taking over 2 hours to run. I have set up all the index's to be correct. But it still takes forever is there something i am missing or a more efficient way of joining tables together that will speed this query up?
I have indexes set up for all items being joined together and they are the same length and data type.
SELECT
p.sap_article_id,
p.numeric_line_code,
p.uag_linecode,
p.uag_partnum,
p.part_description,
p.jobber_price,
p.jobber_core,
p.discount1,
p.discount2,
p.uom,
p.product_category,
w.as400_warehouse,
w.atp_qty,
p.updated,
t.regular_discount
FROM part p
LEFT JOIN tabjbmaw t ON t.accountnum = '73050'
AND p.numeric_line_code = t.numeric_line_code
AND p.sub_code = t.sub_code
JOIN warehouse w ON w.sap_article_id = p.sap_article_id;
+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+
| 1 | SIMPLE | part | ALL | PRIMARY,sap_article,part_sap_article_id_fk | NULL | NULL | NULL | 389309 | |
| 1 | SIMPLE | warehouse | ref | article | article | 130 | inventory.part.sap_article_id | 5 | Using where |
| 1 | SIMPLE | tabjbmaw | ref | numeric_line_code_idx,subcode_idx,accountnum_idx | numeric_line_code_idx | 5 | inventory.part.numeric_line_code | 19 | |
+----+-------------+-----------+------+--------------------------------------------------+-----------------------+---------+----------------------------------+--------+-------------+
Thank you for your help
+-----------------------------+--------------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------+--------------+------+-----+---------------------+-----------------------------+
| sap_article_id | varchar(24) | NO | PRI | | |
| sap_brand_id | varchar(20) | NO | | NULL | |
| uag_partnum | varchar(20) | NO | MUL | NULL | |
| uag_linecode | varchar(5) | NO | MUL | NULL | |
| cag_partnum | varchar(20) | NO | MUL | NULL | |
| cag_linecode | varchar(5) | NO | | NULL | |
| product_category_legacy | varchar(20) | NO | | NULL | |
| part_description | varchar(128) | NO | | NULL | |
| abc_indicator | varchar(8) | NO | | NULL | |
| pack_code | varchar(8) | NO | | NULL | |
| case_qty | int(11) | NO | | NULL | |
| per_car_qty | int(11) | NO | | NULL | |
| uom | varchar(6) | NO | | NULL | |
| upc_code | varchar(128) | NO | | NULL | |
| jobber_price | float(14,4) | YES | | NULL | |
| jobber_core | float(14,4) | YES | | NULL | |
| date_last_price_change | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| weight | float(14,4) | YES | | NULL | |
| weight_unit | varchar(6) | NO | | NULL | |
| dimension_type | varchar(6) | NO | | NULL | |
| length | float(14,4) | YES | | NULL | |
| width | float(14,4) | YES | | NULL | |
| height | float(14,4) | YES | | NULL | |
| updated | tinyint(1) | NO | | 0 | |
| superseded_sap_article_id | varchar(24) | YES | | NULL | |
| last_updated | timestamp | NO | | 0000-00-00 00:00:00 | |
| hour_updated | int(11) | YES | | NULL | |
| discount1 | float | YES | | NULL | |
| discount2 | float | YES | | NULL | |
| product_category | varchar(3) | YES | | NULL | |
| superseded_part_number | varchar(20) | YES | | NULL | |
| sub_code | varchar(3) | YES | MUL | NULL | |
| date_effective_price_change | date | YES | | NULL | |
| numeric_line_code | varchar(3) | YES | MUL | NULL | |
| list | float | YES | | NULL | |
+-----------------------------+--------------+------+-----+---------------------+-----------------------------+
I have indexes set up for all items being joined together
Yes, but I am guessing from the names of the indexes that each index only has one field.
Let's look at a few columns in the describe.
| table | possible_keys | key
+-----------+--------------------------------------------------+----------------
| part | PRIMARY,sap_article,part_sap_article_id_fk | NULL
| warehouse | article | article
| tabjbmaw | numeric_line_code_idx,subcode_idx,accountnum_idx | numeric_line_code_idx
It can use an index for numeric_line_code, subcode, and accountnum, but there are only three indexes each with one of the fields, and no index which has all the fields. You are making the optimizer choose one of the one field indexes, instead of providing one index it can use for all three fields.
Add an index on table tabjbmaw with the three fields numeric_line_code, subcode, and accountnum.
Extending #Sebas answer, you should select tabjbmaw first:
SELECT
p.sap_article_id,
p.numeric_line_code,
p.uag_linecode,
p.uag_partnum,
p.part_description,
p.jobber_price,
p.jobber_core,
p.discount1,
p.discount2,
p.uom,
p.product_category,
w.as400_warehouse,
w.atp_qty,
p.updated,
t.regular_discount
FROM tabjbmaw t
LEFT JOIN parts p ON p.numeric_line_code = t.numeric_line_code
AND p.sub_code = t.sub_code
JOIN warehouse w ON w.sap_article_id = p.sap_article_id
WHERE t.accountnum = '73050'
;
You could try to put your Left Join into the SELECT part as a Subselect. That 'may' speed things up a little.
Like this:
SELECT
p.sap_article_id,
p.numeric_line_code,
p.uag_linecode,
p.uag_partnum,
p.part_description,
p.jobber_price,
p.jobber_core,
p.discount1,
p.discount2,
p.uom,
p.product_category,
w.as400_warehouse,
w.atp_qty,
p.updated,
(SELECT t.regular_discount FROM tabjbmaw t WHERE t.accountnum = '73050' AND p.numeric_line_code = t.numeric_line_code AND p.sub_code = t.sub_code LIMIT 1)
FROM
part p
JOIN warehouse w ON w.sap_article_id = p.sap_article_id;