How to use inner join in select with mysql? - mysql

I want to fetch record from mysql database on following condition
I have the following tables:
organization_ Table
organizationId | organizationname
campaign Table
camp_id | camp_name | adv_id | organizationId
advertise Table
adv_id | adv_name
ad_display Table
ad_displayId | adv_id | camp_id |
Now from ad_display table I want to fetch record like this:
| adv_name | camp_name | organizationname
With WHERE Condtion as Where organizationId == ?
So basically I want the advertise list of campaign where organization_id=?
Note: there should be multiple entry for same adv_id in camapign table and same camp_id with multiple entry in ad_display

Try this:
SELECT ad.ad_displayId, a.adv_name, c.camp_name, o.organizationname
FROM ad_display ad
INNER JOIN advertise a ON ad.adv_id = a.adv_id
INNER JOIN campaign c ON ad.camp_id = c.camp_id
INNER JOIN organization o ON c.organizationId = o.organizationId
WHERE o.organizationId = ?;

Maybe something like this?
SELECT Distinct
advertise.adv_name,
campaign.camp_name,
organization_.organizationname
FROM
advertise inner join campaign
on advertise.adv_id = campaign.adv_id
inner join organization_
on campaign.organizationID = organization_.organizationID
WHERE
organization_.organizationID = 1

SELECT advertise.adv_name,
campaign.camp_name,
organization_Table.organizationname
FROM ad_display
INNER JOIN advertise ON ad_display.adv_id = advertise.adv_id
INNER JOIN campaign ON ad_display.camp_id = campaign.camp_id
INNER JOIN organization_ Table ON campaign.organizationId = organization_Table.organizationId
AND organization_Table.organizationId=?

SELECT * FROM campaign
LEFT JOIN ad_display ON campaign.camp_id = ad_display.camp_id
LEFT JOIN advertise ON ad_display.adv_id = advertise.adv_id
WHERE campaign.organizationId = <?>

Use below code
SELECT dv_name,
camp_name,
organizationname
FROM organization
inner join campaign
ON organization.organizationid == campaign.organizationid
left join advertise
ON campaign.adv_id == advertise.adv_id
WHERE condition =? ;

SELECT batch_number,
Count(receipt_number) AS tot_rec,
Sum(amount) AS tot_amount
FROM receipt_header
GROUP BY batch_number
UNION ALL
SELECT batch_number,
Count(receipt_lines.receipt_number),
Sum(receipt_lines.amount)
FROM receipt_lines
INNER JOIN receipt_header
ON receipt_header.record_id = receipt_lines.header_record_id
GROUP BY batch_number
ORDER BY batch_number ASC;

Related

Using parent id in child query?

SELECT li_1.carrier, li_1.product_id, li_1.quantity, products_description.products_name, sites.sites_id, sites.sites_name, counted_table.counted
FROM inventory li_1
INNER JOIN products_description ON li_1.product_id = products_description.products_id
INNER JOIN sites ON products_description.data = sites.data
INNER JOIN (
SELECT SUM( li_2.quantity ) AS counted
FROM inventory li_2
WHERE li_1.product_id = li_2.product_id
) counted_table
GROUP BY li_1.product_id
ORDER BY li_1.id DESC
I'm attempting to use the parent id (product_id) to count the total amount of quantity for each product in the subquery - But I only get the standard mysql error message.
So something like
id | quantity | total
---------------------------------
0001 | 2 | 6
| |
0001 | 4 | 6
What could be wrong?
if you change sub-query, it could be fixed
SELECT li_1.carrier, li_1.product_id, li_1.quantity, products_description.products_name, sites.sites_id, sites.sites_name, counted_table.counted
FROM inventory li_1
INNER JOIN products_description ON li_1.product_id = products_description.products_id
INNER JOIN sites ON products_description.data = sites.data
INNER JOIN (
SELECT product_id,SUM( li_2.quantity ) AS counted
FROM inventory li_2
GROUP BY li_2.product_id
) counted_table ON li_1.product_id = counted_table.product_id
ORDER BY li_1.id DESC

How can I optimize my sql code?

I have following tables
contacts
contact_id | contact_slug | contact_first_name | contact_email | contact_date_added | company_id | contact_is_active | contact_subscribed | contact_last_name | contact_company | contact_twitter
contact_campaigns
contact_campaign_id | contact_id | contact_campaign_created | company_id | contact_campaign_sent
bundle_feedback
bundle_feedback_id | bundle_id, contact_id | company_id | bundle_feedback_rating | bundle_feedback_favorite_track_id | bundle_feedback_supporting | campaign_id
bundles
bundle_id | bundle_name | bundle_created | company_id | bundle_is_active
tracks
track_id | company_id | track_title
I wrote this query, but it works slowly, how can I optimize this query to make it faster ?
SELECT SQL_CALC_FOUND_ROWS c.contact_id,
c.contact_first_name,
c.contact_last_name,
c.contact_email,
c.contact_date_added,
c.contact_company,
c.contact_twitter,
concat(c.contact_first_name," ", c.contact_last_name) AS fullname,
c.contact_subscribed,
ifnull(icc.sendCampaignsCount, 0) AS sendCampaignsCount,
ifnull(round((ibf.countfeedbacks/sendCampaignsCount * 100),2), 0) AS percentFeedback,
ifnull(ibf.bundle_feedback_supporting, 0) AS feedbackSupporting
FROM contacts AS c
LEFT JOIN
(SELECT c.contact_id,
count(cc.contact_campaign_id) AS sendCampaignsCount
FROM contacts AS c
LEFT JOIN contact_campaigns AS cc ON cc.contact_id = c.contact_id
WHERE c.company_id = '876'
AND c.contact_is_active = '1'
AND cc.contact_campaign_sent = '1'
GROUP BY c.contact_id) AS icc ON icc.contact_id = c.contact_id
LEFT JOIN
(SELECT bf.contact_id,
count(*) AS countfeedbacks,
bf.bundle_feedback_supporting
FROM bundle_feedback bf
JOIN bundles b
JOIN contacts c
LEFT JOIN tracks t ON bf.bundle_feedback_favorite_track_id = t.track_id
WHERE bf.bundle_id = b.bundle_id
AND bf.contact_id = c.contact_id
AND bf.company_id='876'
GROUP BY bf.contact_id) AS ibf ON ibf.contact_id = c.contact_id
WHERE c.company_id = '876'
AND contact_is_active = '1'
ORDER BY percentFeedback DESC LIMIT 0, 25;
I have done 2 improvements
1) Removed the contacts which is getting joined unnecessarily twice and put the condition at the final where condition.
2) Removed as per SQL_CALC_FOUND_ROWS
Which is fastest? SELECT SQL_CALC_FOUND_ROWS FROM `table`, or SELECT COUNT(*)
SELECT c.contact_id,
c.contact_first_name,
c.contact_last_name,
c.contact_email,
c.contact_date_added,
c.contact_company,
c.contact_twitter,
concat(c.contact_first_name," ", c.contact_last_name) AS fullname,
c.contact_subscribed,
ifnull(icc.sendCampaignsCount, 0) AS sendCampaignsCount,
ifnull(round((ibf.countfeedbacks/sendCampaignsCount * 100),2), 0) AS percentFeedback,
ifnull(ibf.bundle_feedback_supporting, 0) AS feedbackSupporting
FROM contacts AS c
LEFT JOIN
(SELECT cc.contact_id,
count(cc.contact_campaign_id) AS sendCampaignsCount
FROM contact_campaigns
WHERE cc.contact_campaign_sent = '1'
GROUP BY cc.contact_id) AS icc ON icc.contact_id = c.contact_id
LEFT JOIN
(SELECT bf.contact_id,
count(*) AS countfeedbacks,
bf.bundle_feedback_supporting
FROM bundle_feedback bf
JOIN bundles b
LEFT JOIN tracks t ON bf.bundle_feedback_favorite_track_id = t.track_id
WHERE bf.bundle_id = b.bundle_id
GROUP BY bf.contact_id) AS ibf ON ibf.contact_id = c.contact_id
WHERE c.company_id = '876' and c.contact_is_active = '1'
First, you are not identifying any indexes you have to optimize the query. That said, I would ensure you have at least the following composite / covering indexes.
table index
contacts ( company_id, contact_is_active )
contact_campaigns ( contact_id, contact_campaign_sent )
bundle_feedback ( contact_id, bundle_feedback_supporting )
Next, as noted in other answer, unless you really need how many rows qualified, remove the "SQL_CALC_FOUND_ROWS".
In your first left-join (icc), you do a left-join on contact_campaigns (cc), but then throw into your WHERE clause an "AND cc.contact_campaign_sent = '1'" which turns that into an INNER JOIN. At the outer query level, these would result in no matching record and thus NULL for your percentage calculations.
In your second left-join (ibf), you are doing a join to the tracks table, but not utilizing anything from it. Also, you are joining to the bundles table but not using anything from there either -- unless you are getting multiple rows in the bundles and tracks tables which would result in a Cartesian result and possibly overstate your "CountFeedbacks" value. You also do not need the contacts table as you are not doing anything else with it, and the feedback table has the contact ID basis your are querying for. Since that is only grouped by the contact_id, your "bf.bundle_feedback_supporting" is otherwise wasted. If you want counts of feedback, just count from that table per contact ID and remove the rest. (also, the joins should have the "ON" clauses instead of within the WHERE clause for consistency)
Also, for your supporting feedback, the data type and value are unclear, so I implied as a Yes or No and have a SUM() based on how many are supporting. So, a given contact may have 100 records but only 37 are supporting. This gives you 1 record for the contact having BOTH values 100 and 37 respectively and not lost in a group by based on the first entry found for the contact.
I would try to summarize your query to below:
SELECT
c.contact_id,
c.contact_first_name,
c.contact_last_name,
c.contact_email,
c.contact_date_added,
c.contact_company,
c.contact_twitter,
concat(c.contact_first_name," ", c.contact_last_name) AS fullname,
c.contact_subscribed,
ifnull(icc.sendCampaignsCount, 0) AS sendCampaignsCount,
ifnull(round((ibf.countfeedbacks / icc.sendCampaignsCount * 100),2), 0) AS percentFeedback,
ifnull(ibf.SupportCount, 0) AS feedbackSupporting
FROM
contacts AS c
LEFT JOIN
( SELECT
c.contact_id,
count(*) AS sendCampaignsCount
FROM
contacts AS c
JOIN contact_campaigns AS cc
ON c.contact_id = cc.contact_id
AND cc.contact_campaign_sent = '1'
WHERE
c.company_id = '876'
AND c.contact_is_active = '1'
GROUP BY
c.contact_id) AS icc
ON c.contact_id = icc.contact_id
LEFT JOIN
( SELECT
bf.contact_id,
count(*) AS countfeedbacks,
SUM( case when bf.bundle_feedback_supporting = 'Y'
then 1 else 0 end ) as SupportCount
FROM
contacts AS c
JOIN bundle_feedback bf
ON c.contact_id = bf.contact_id
WHERE
c.company_id = '876'
AND c.contact_is_active = '1'
GROUP BY
bf.contact_id) AS ibf
ON c.contact_id = ibf.contact_id
WHERE
c.company_id = '876'
AND c.contact_is_active = '1'
ORDER BY
percentFeedback DESC LIMIT 0, 25;

How do I pull out data from a group of tables based on an related table value with SQLite?

I have a set of tables:
1) **nanoInst**:
rid | api_id | name | instLoc | instText | pixelPitch | logo | listImg
2) **nanoFiles**:
rid | api_id | name | fileType | fileLoc
3) **nanoInd**:
rid | api_id | name
4) **nanoRelInd**:
rid | inst_id | ind_id
5) **nanoGalleries**:
rid | inst_id | file_id | gallery_order
My original SQL statement simple selected the the id and name from the nanoInst table, the fileLoc from nanoFiles and the name from nanoInd where nanoInst had the nanoFile id stored, and where nanoInst and nanoInd were realted a their ids.
SELECT
nanoInst.rid as instID,
nanoInst.name AS nanoName,
nanoFiles.fileLoc AS nanoFile,
nanoInd.name AS indName
FROM nanoInst
LEFT JOIN nanoFiles ON nanoInst.logo = nanoFiles.rid
LEFT JOIN nanoRelInd ON nanoInst.rid = nanoRelInd.inst_id
LEFT JOIN nanoInd ON nanoRelInd.ind_id = nanoInd.rid
I need to adjust this statement so I only get results where nanoFiles.fileType is 'video'. I tried simply adding WHERE nanoFiles.fileType='video' but 0 rows are returned but I know some exist.
--- EDIT ---
I've found that if I can count the number of items with videos for that row then run a WHERE clause to filter:
SELECT
nanoInst.rid as instID,
nanoInst.name AS nanoName,
nanoFiles.fileLoc AS nanoFile,
nanoInd.name AS indName,
nanoFiles.fileType as nanoType,
(SELECT
COUNT(nanoGalleries.rid)
FROM nanoGalleries
LEFT JOIN nanoFiles ON nanoFiles.rid = nanoGalleries.file_id
LEFT JOIN nanoInst ON nanoInst.rid = nanoGalleries.inst_id
WHERE nanoFiles.fileType = 'video') AS vidCount
FROM
nanoInst
LEFT JOIN nanoFiles ON nanoInst.logo = nanoFiles.rid
LEFT JOIN nanoRelInd ON nanoInst.rid = nanoRelInd.inst_id
LEFT JOIN nanoInd ON nanoRelInd.ind_id = nanoInd.rid
WHERE vidCount > 0
The issue is vidCount returns the total number of videos for not just the count for that row / nanoInst.rid
The records may be getting filtered out due to no matching records in nanoRelInd or nanoInd. If that is the case, this should work.
SELECT
nanoInst.rid as instID,
nanoInst.name AS nanoName,
nanoFiles.fileLoc AS nanoFile,
nanoInd.name AS indName
FROM
nanoInst
LEFT JOIN nanoFiles ON nanoInst.logo = nanoFiles.rid
LEFT outer JOIN nanoRelInd ON nanoInst.rid = nanoRelInd.inst_id
LEFT outer JOIN nanoInd ON nanoRelInd.ind_id = nanoInd.rid
WHERE
nanoFiles.fileType='video'
based on the comments in your original post and the sqlfiddle you provided:
SELECT *
FROM nanogalleries
LEFT JOIN nanofiles on(nanofiles.rid=nanogalleries.file_id)
WHERE nanofiles.filetype='video';
http://sqlfiddle.com/#!9/e318a/1/0
Updated answer based on comments
SELECT nanogalleries.inst_id,
nanoinst.name AS nanoName,
nanoFiles.fileLoc,
nanoInd.name AS indName,
count(nanogalleries.inst_id) AS vidCount
FROM nanogalleries
LEFT JOIN nanofiles ON nanofiles.rid = nanogalleries.file_id
LEFT JOIN nanoinst ON nanoinst.rid = nanogalleries.inst_id
LEFT JOIN nanoRelInd ON nanoinst.rid = nanoRelInd.inst_id
LEFT JOIN nanoInd ON nanoind.rid = nanorelind.ind_id
WHERE nanofiles.filetype = 'video'
GROUP BY nanogalleries.inst_id;
http://sqlfiddle.com/#!9/e318a/50/1

MySQL multiple inner join between 2 tables on different columns for one of the tables

Table transport
Id | FirstLevSubcat | SecondLevSubcat | ThirdLevSubcat
--------------------------------------------------------
8 | 4 | 27 | 1418
Table categories
Id | CategoriesUrl
--------------------
4 | cars
27 | audi
1418 | audi-100
Query if not to use categories table (without inner join) would be like
SELECT count(*) FROM transport
WHERE FirstLevSubcat = 4 AND SecondLevSubcat = 27 AND ThirdLevSubcat = 1418
Trying to get the same result using INNER JOIN
SELECT count(*) FROM transport main_table
INNER JOIN categories cat_table_first ON cat_table_first.IdRows = main_table.FirstLevSubcat
INNER JOIN categories cat_table_second ON cat_table_second.IdRows = main_table.SecondLevSubcat
INNER JOIN categories cat_table_third ON cat_table_third.IdRows = main_table.ThirdLevSubcat
WHERE
cat_table_first.CategoriesUrl = 'cars'
AND cat_table_second.CategoriesUrl = 'audi'
AND cat_table_third.CategoriesUrl = 'audi-100'
At first sight all works
But is such query ok? May be can improve something?
Your query is correct. You can also do it in following way:
SELECT count(*) FROM transport main_table
INNER JOIN categories cat_table_first ON cat_table_first.IdRows = main_table.FirstLevSubcat and cat_table_first.CategoriesUrl = 'cars'
INNER JOIN categories cat_table_second ON cat_table_second.IdRows = main_table.SecondLevSubcat and cat_table_second.CategoriesUrl = 'audi'
INNER JOIN categories cat_table_third ON cat_table_third.IdRows = main_table.ThirdLevSubcat and cat_table_third.CategoriesUrl = 'audi-100'
You can also do it using 3 EXISTS block.
SELECT count(*) FROM transport main_table
WHERE
EXISTS (SELECT NULL FROM categories WHERE main_table.FirstLevSubcat=categories.IdRows AND categories.CategoriesUrl ='cars')
AND
EXISTS (SELECT NULL FROM categories WHERE main_table.SecondLevSubcat=categories.IdRows AND categories.CategoriesUrl ='audi')
AND
EXISTS (SELECT NULL FROM categories WHERE main_table.ThirdLevSubcat=categories.IdRows AND categories.CategoriesUrl ='audi-100')

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';