I have two tables. 'First' table contains 2 ids of 'second' table. v2 and v3 are second table's IDs.
First:
`id`, `mem`, `v2`, `v3`, `v2_amt`, `v3_amt`
1, 'test', 1, 2, '10', '20'
2, 'test2', 1, 2, '10', ''
Second:
`id`, `name`
1, 'anna'
2, 'teena'
When I'm joining,
SELECT f.mem, s.name
FROM `first` f
JOIN second s
ON f.v2 = s.id
AND f.v2_amt !=""
AND (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '1'
GROUP BY s.id
Currenlty it return none.
Is any way to union both tables to achieve output as following..??
`mem`, `name`
test, 'anna'
test, 'teena'
For fetching 2 id of first table.
SELECT f.mem, s.name
FROM `first` f
JOIN second s
ON f.v2 = s.id
AND f.v2_amt !=""
AND (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '2'
GROUP BY s.id
It should return as, seems v3_amt is empty.
`mem`, `name`
test, 'anna'
You should empty the v3 column on insert if v3_amt="" similarly on v2 and try this query
Select f.v2,f.v3,f.v2_amt,f.v3_amt,s.name from first as f join second as s on
(f.v2 = s.id OR f.v3 = s.id) and (f.v2_amt!="" OR f.v3_amt!="") where f.id=2
:)
You should use OR.
SELECT f.mem, s.name FROM `first` f JOIN `second` s
ON f.v2 = s.id AND f.v2_amt !="" OR (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '1'
you can use left join and OR for this case
select ft.mem, st.name from first_table ft
LEFT JOIN second_table st ON (ft.v2 = st.id AND ft.v2_amt !="") OR (ft.v3 = st.id AND ft.v3_amt !="")
WHERE ft.id = '1'
I have a query that I want to optimize. Both unions executed separatley run fine, however as soon as I include inner join it takes up to 57 seconds. How do I solve this. My query is as follows
SELECT
p.PROJID,
p.StartDate,
o.ORDERNO,
p.PROJCODE,
p.PROJECT,
cat.type AS CATEGORY,
p.AREA,
p.STATE,
p.COUNTRY,
p.VALUE,
p.PROCESSOR,
p.PROJINFO,
p.NES,
p.SPECSALE,
p.OFFICE,
p.DEPTCODE,
p.INTERNLCHG,
p.INTERCOCHG,
p.LORM,
p.PERCENT,
d.COMPANY,
CONCAT(
d.LASTNAME,
", ",
d.FIRSTNAME
) AS Contact
FROM
(
(
SELECT
*
FROM
(
SELECT
`clients`.`CLIENTID` AS `CLIENTIDA`,
`clients`.`COMPANY` AS `COMPANY`
FROM
`hdb`.`clients`
UNION
SELECT
`accounts`.`id` AS `CLIENTIDA`,
`accounts`.`name` AS `COMPANY`
FROM
`sugarcrm`.`accounts`
) AS a
INNER JOIN (
SELECT
`hdb`.`contacts`.`CONTACTID` AS `CONTACTID`,
`hdb`.`contacts`.`CLIENTID` AS `CLIENTIDC`,
`hdb`.`contacts`.`FIRSTNAME` AS `FIRSTNAME`,
`hdb`.`contacts`.`LASTNAME` AS `LASTNAME`
FROM
`hdb`.`contacts`
UNION
SELECT
`sugarcrm`.`contacts`.`id` AS `CONTACTID`,
`sugarcrm`.`accounts_contacts`.`account_id` AS `CLIENTIDC`,
`sugarcrm`.`contacts`.`first_name` AS `FIRSTNAME`,
`sugarcrm`.`contacts`.`last_name` AS `LASTNAME`
FROM
`sugarcrm`.`contacts`
LEFT JOIN `sugarcrm`.`accounts_contacts` ON `sugarcrm`.`contacts`.`id` = `sugarcrm`.`accounts_contacts`.`contact_id`
) AS c ON a.CLIENTIDA = c.CLIENTIDC
) AS d
)
INNER JOIN (
(
projects AS p
INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO
)
INNER JOIN category AS cat ON p.category_id = cat.category_id
) ON d.CONTACTID = o.CONTACTID
Explain on this provides the following:
1, PRIMARY, cat, ALL, PRIMARY, , , , 10,
1, PRIMARY, p, ref, FK_orders_projects,FK_category_projects_idx, FK_category_projects_idx, 5, hdb.cat.category_id, 400, Using where
1, PRIMARY, o, eq_ref, PRIMARY, PRIMARY, 4, hdb.p.ORDERNO, 1,
1, PRIMARY, <derived2>, ALL, , , , , 18878, Using where
2, DERIVED, <derived3>, ALL, , , , , 7087,
2, DERIVED, <derived5>, ALL, , , , , 18879, Using where
5, DERIVED, contacts, ALL, , , , , 8261,
6, UNION, contacts, ALL, , , , , 10251,
6, UNION, accounts_contacts, ref, idx_contid_del_accid, idx_contid_del_accid, 111, sugarcrm.contacts.id, 1, Using index
, UNION RESULT, <union5,6>, ALL, , , , , ,
3, DERIVED, clients, ALL, , , , , 2296,
4, UNION, accounts, ALL, , , , , 4548,
, UNION RESULT, <union3,4>, ALL, , , , , ,
The original query without the union takes 0.125 seconds
SELECT p.PROJID, p.StartDate, o.ORDERNO, p.PROJCODE, p.PROJECT, cat.type AS CATEGORY, p.AREA, p.STATE, p.COUNTRY,
p.VALUE, p.PROCESSOR, p.PROJINFO, p.NES, p.SPECSALE, p.OFFICE, p.DEPTCODE, p.INTERNLCHG, p.INTERCOCHG, p.LORM,
p.PERCENT, a.COMPANY, CONCAT(c.LASTNAME, ", ", c.FIRSTNAME) AS Contact
FROM (clients AS a
INNER JOIN contacts AS c ON a.CLIENTID =c.CLIENTID)
INNER JOIN ((projects AS p INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO)
INNER JOIN category AS cat ON p.category_id = cat.category_id) ON c.CONTACTID = o.CONTACTID
ORDER BY p.PROJID, a.COMPANY;
explain on this provides following:
1, SIMPLE, cat, ALL, PRIMARY, , , , 10, Using temporary; Using filesort
1, SIMPLE, p, ref, FK_orders_projects,FK_category_projects_idx, FK_category_projects_idx, 5, hdb.cat.category_id, 400, Using where
1, SIMPLE, o, eq_ref, PRIMARY,FK_contacts_orders, PRIMARY, 4, hdb.p.ORDERNO, 1,
1, SIMPLE, c, eq_ref, PRIMARY,FK_clients_contacts, PRIMARY, 52, hdb.o.CONTACTID, 1,
1, SIMPLE, a, eq_ref, PRIMARY, PRIMARY, 52, hdb.c.CLIENTID, 1,
Query with view:
SELECT
p.PROJID,
p.StartDate,
o.ORDERNO,
p.PROJCODE,
p.PROJECT,
cat.type AS CATEGORY,
p.AREA,
p.STATE,
p.COUNTRY,
p.VALUE,
p.PROCESSOR,
p.PROJINFO,
p.NES,
p.SPECSALE,
p.OFFICE,
p.DEPTCODE,
p.INTERNLCHG,
p.INTERCOCHG,
p.LORM,
p.PERCENT,
a.COMPANY,
CONCAT(
c.LASTNAME,
", ",
c.FIRSTNAME
) AS Contact
FROM
(
view_accounts_sugar_hdb AS a
INNER JOIN view_contacts_sugar_hdb AS c ON a.CLIENTID = c.CLIENTID
)
INNER JOIN (
(
projects AS p
INNER JOIN orders AS o ON p.ORDERNO = o.ORDERNO
)
INNER JOIN category AS cat ON p.category_id = cat.category_id
) ON c.CONTACTID = o.CONTACTID
ORDER BY
p.PROJID,
a.COMPANY;
This takes over 340 secs.
This one was definitely uglier than the last one I helped you on :)... Anyhow, the same principles apply. For future, please do try to understand what I'm doing here. Write the JOIN relationships FIRST to know where your data is coming from. Also, take a look at my indentations... I am showing at each level for readability.
Orders -> Projects -> Categories...
then, the path for those in the normal clients table via
Orders -> Contacts -> Clients
finally to the SugarCRM contacts...
Orders -> Accounts_Contacts -> Accounts
So, now that you have the relationships set (and aliased), this follows similar of last answer implementing LEFT-JOIN to normal contact/client vs CRM Contacts/Accounts.
The field list is simple on the Order, Products and Category tables as those are pretty direct. That leaves just the "who/client" information where the LEFT-JOIN comes in. If the Normal client is null, use the CRM version fields, otherwise use the normal client fields...
SELECT
P.PROJID,
P.StartDate,
O.ORDERNO,
P.PROJCODE,
P.PROJECT,
cat.`type` AS CATEGORY,
P.AREA,
P.STATE,
P.COUNTRY,
P.VALUE,
P.PROCESSOR,
P.PROJINFO,
P.NES,
P.SPECSALE,
P.OFFICE,
P.DEPTCODE,
P.INTERNLCHG,
P.INTERCOCHG,
P.LORM,
P.PERCENT,
CASE when HCLIENT.ClientID IS NULL
then SCLIENT.`name`
ELSE HCLIENT.Company end as Company,
CASE when HCLIENT.ClientID IS NULL
then CONCAT( SCT.LAST_NAME, ", ", SCT.FIRST_NAME )
ELSE CONCAT( HCT.LASTNAME, ", ", HCT.FIRSTNAME ) end as Contact
FROM
orders O
JOIN projects P
ON O.OrderNo = P.OrderNo
JOIN category AS cat
ON p.category_id = cat.category_id
LEFT JOIN hdb.contacts HCT
ON O.ContactID = HCT.ContactID
LEFT JOIN hdb.clients HCLIENT
ON HCT.ClientID = HCLIENT.ClientID
LEFT JOIN sugarcrm.contacts SCT
ON O.ContactID = SCT.ID
LEFT JOIN sugarcrm.accounts_contacts SAC
ON SCT.ID = SAC.contact_id
LEFT JOIN sugarcrm.accounts SCLIENT
ON SCT.account_id = SCLIENT.ID
I'd be interested in the performance improvement too.
I have the following tables.
PHONES
- id
- name
- colour
- size
STOCK
- store_id
- phone_id
- instock
STORES
- id
- name
LINKS
- store_id
- phone_id
- url
I want to SELECT name, colour, size from PHONES, instock from STOCK, name from STORES, and url from LINKS WHERE stock.phone_id = phones.id = links.phone_id AND stock.store_id = links.store_id AND stores.id = stock.store_id.
I want out put, phone.name, phone.colour, phone.size, stock.instock, stores.name, links.url.
This is my current query. I am not getting specific links back related to that store AND phone id's.
SELECT DISTINCT(s.phone_id), st.name, st.logo_url, l.url, s.instock, s.datetime, p.model, p.colour, p.size
FROM stock AS s, stores AS st
INNER JOIN links AS l, phones AS p
WHERE s.phone_id = p.id
AND s.phone_id = l.phone_id
AND s.store_id = l.store_id
AND s.store_id IN ('3','4','5','6','8')
AND s.phone_id = '5'
ORDER BY datetime
DESC LIMIT 5
SELECT p.name, p.colour, p.size, st.instock, s.name, l.url
FROM phones p
INNER JOIN links l ON l.phone_id = p.id
INNER JOIN stores s ON s.id = l.store_id
INNER JOIN stock st ON st.store_id = s.id AND st.phone_id = p.id
WHERE s.id IN ('3', '4', '5', '6', '8')
AND p.id = '5'
datetime isn't defined in your table description so I neglected to add it to the query, but this should provide what you are looking.
I have an existing query:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
which is defined in a php page. I've been asked to add another parameter which is stored in another table, the problem is, on sds_product can have many "communications" which is basicly like a comment with a date_created. For example, if I wanted a list of communications for a given product, I would do:
select * from sds_product_comms as pc
join sds_comms c on pc.comms_id = c.comms_id
where prod_id = 2546
I wanted to do this directly in SQL, so is it possible to somehow make a sub query to stick these two together, without creating duplicate rows in the initial query.
For example I don't want 5 rows of the same product with the same max date_created.
desc sds_comms
'comms_id', 'int(10) unsigned', 'NO', 'PRI', '', 'auto_increment'
'method', 'int(10) unsigned', 'NO', '', '', ''
'dialogue', 'varchar(200)', 'NO', '', '', ''
'reply_id', 'int(10) unsigned', 'NO', '', '', ''
'comm_to', 'varchar(60)', 'NO', '', '', ''
'comm_from', 'varchar(60)', 'NO', '', '', ''
'man_id', 'int(10) unsigned', 'NO', '', '', ''
'supp_id', 'int(10) unsigned', 'NO', '', '', ''
'user_id', 'int(10) unsigned', 'NO', '', '', ''
'date_created', 'timestamp', 'NO', '', 'CURRENT_TIMESTAMP', ''
Sorry for the detail but its hard to get my head around it!
EDIT:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
,lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join (select comms_id, max(date_created) as lastContact from sds_comms group by comms_id ) as c2 on pc.comms_id = c2.comms_id
where productID=555;
would this be a correct way of doing it? With this method I'm getting different lastContact dates for the same productID :(
Try this:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID,
c.date_created as lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join comms_id c on c.comms_id = pc.comms_id and c.date_created = (select max(date_created) from comms_id c2 where c2.comms_id = pc.comms_id)
where productID=555;
If I understand you correctly, you want a parameter that is in a table that is on the N end of a 1:N relationship and you want to have only 1 of each.
You can try grouping your data using GROUP BY.
Something like:
SELECT sds_product_comms.*, MAX(sds_comms.created_at) FROM sds_product_comms AS pc
JOIN sds_comms c ON pc.comms_id = c.comms_id
GROUP BY sds_product_comms.prod_id