MySQL Query depending on column value define where statement - mysql

I have this SQL:
SELECT
`refnumbers`.`order_id`,
`refnumbers`.`deal_id`,
`refnumbers`.`claim_track_id`,
`deals`.`partner_count`
FROM `refnumbers`
JOIN `deals`
ON (`refnumbers`.`deal_id` = `deals`.`ID`)
JOIN `users`
ON (`users`.`id` = `deals`.`partner_id`)
WHERE `refnumbers`.`is_claimed` = '1'
AND `deals`.`partner_id` = '62039'
AND `refnumbers`.`claimed_at` BETWEEN '2013-01-17 00:00:00'
AND '2013-01-17 23:59:59'
ORDER BY `refnumbers`.`claimed_at` DESC
I would like to select where deals.partner_id = 62039 IF deals.partner_count is 1.
If partner_count isnt 1 then it should select where refnumbers.claim_track_id = 62039
How can this be done?

try
where
case when deals.partner_count = 1
then deals.partner_id = 62039
else refnumbers.claim_track_id = 62039
end

You need to have a condition enclose in a parenthesis which uses OR
SELECT `refnumbers`.`order_id`,
`refnumbers`.`deal_id`,
`refnumbers`.`claim_track_id`,
`deals`.`partner_count`
FROM `refnumbers`
INNER JOIN `deals`
ON (`refnumbers`.`deal_id` = `deals`.`ID`)
INNER JOIN `users`
ON (`users`.`id` = `deals`.`partner_id`)
WHERE `refnumbers`.`is_claimed` = '1' AND
`refnumbers`.`claimed_at` BETWEEN '2013-01-17 00:00:00' AND '2013-01-17 23:59:59'
AND
(
(deals.partner_id = 62039 AND deals.partner_count = 1)
OR
(refnumbers.claim_track_id = 62039 AND deals.partner_count <> 1)
)
ORDER BY `refnumbers`.`claimed_at` DESC

Try this:
SELECT r.order_id, r.deal_id,r.claim_track_id, d.partner_count
FROM refnumbers r
INNER JOIN deals d ON r.deal_id = d.ID
INNER JOIN users u ON d.partner_id = u.id
WHERE IF(d.partner_count = 1, d.partner_id = '62039', r.claim_track_id = 62039) AND
r.is_claimed = '1' AND r.claimed_at BETWEEN '2013-01-17 00:00:00' AND '2013-01-17 23:59:59'
ORDER BY r.claimed_at DESC

Related

Query WHERE NOT IN (SELECT) INNER JOIN

SELECT
SUM(m_out) AS totalOut
FROM
m_detal
WHERE
opers = '25'
AND (m_type = 'Out'
OR m_type = 'Merged')
AND m_date <= '2018-11-28 07:30:00'
AND mark_delete IS NULL
AND m_ids NOT IN (SELECT
m.m_ids
FROM
(SELECT
m_ids
FROM
m_detal
WHERE
opers = '25'
AND (m_type = 'Out'
OR m_type = 'Merged')
AND (m_onhold != 'onhold'
OR m_onhold IS NULL)
AND mark_delete IS NULL
AND m_date <= '2018-11-28 07:30:00') AS m
INNER JOIN
n_combine_tbl AS t ON (t.comb_id1 = m.m_ids
OR t.comb_id2 = m.m_ids)
AND t.time <= '2018-11-28 07:30:00');
This query took me more than 30sec or more! The query inside the NOT IN is little bit huge around 7-9k of ids. Is there a more efficient way of doing this? I think the inner join part is make it slow where the checking the two column of n_combine_tables which is (comb_id1 or comb_id2).
Is there a more efficient way of doing this?
I'd remove duplicated conditions in sub-queries and do something like this (two NOT in could be replaced with UNION):
SELECT
SUM(m.m_out) AS totalOut
FROM
m_detal AS m
WHERE
m.opers = '25'
AND m.m_type IN ('Out', 'Merged')
AND m.m_date <= '2018-11-28 07:30:00'
AND m.mark_delete IS NULL
AND m.m_onhold = 'onhold'
AND m.m_ids NOT IN (
SELECT
t1.comb_id1
FROM
n_combine_tbl AS t1
WHERE
t1.time <= '2018-11-28 07:30:00'
)
AND m.m_ids NOT IN (
SELECT
t2.comb_id2
FROM
n_combine_tbl AS t2
WHERE
t2.time <= '2018-11-28 07:30:00'
)
;
OR with NOT EXISTS:
SELECT
SUM(m.m_out) AS totalOut
FROM
m_detal AS m
WHERE
m.opers = '25'
AND m.m_type IN ('Out', 'Merged')
AND m.m_date <= '2018-11-28 07:30:00'
AND m.mark_delete IS NULL
AND m.m_onhold = 'onhold'
AND NOT EXISTS (
SELECT
*
FROM
n_combine_tbl AS t
WHERE
t.time <= '2018-11-28 07:30:00'
AND (
t.comb_id1 = m.m_ids
OR t.comb_id2 = m.m_ids
)
)
;
You should check the 'onhold' logic.
You should try to add indexes on n_combine_tbl: (time, comb_id1), (time, comb_id2), (comb_id1, time), (comb_id2, time) and check what is good for your data.
Multi-column indexes on m_detal table should also be considered.

Using If Else in Mysql

SELECT process.process_name, com_jobcard.job_card_num,
IF process.UOM = '1' THEN SET (com_jobcard.dept_qty) AS Total_qty
ELSEIF process.UOM = '2' THEN SET (com_jobcard.total_stones) AS Total_qty
FROM timer_completed
INNER JOIN PROCESS ON process.id = timer_completed.process_id
INNER JOIN com_jobcard ON timer_completed.job_card_id = com_jobcard.id
AND timer_completed.report_date = '2015-09-15'
Hi friends I would like to retrieve the value of department quantity When process.UOM = 1 else if process.UOM = '2' THEN SET (com_jobcard.total_stones) AS Total_qty , please help me with the code , thanks in advance
You can use case-when something as
SELECT
process.process_name,
com_jobcard.job_card_num,
case
when process.UOM = '1' then com_jobcard.dept_qty
when process.UOM = '2' then com_jobcard.total_stones
end as Total_qty
FROM timer_completed
INNER JOIN PROCESS ON process.id = timer_completed.process_id
INNER JOIN com_jobcard ON timer_completed.job_card_id = com_jobcard.id
AND timer_completed.report_date = '2015-09-15'
NOTE : Right now there is no else so its better to add an else if both condition fails
case
when process.UOM = '1' then com_jobcard.dept_qty
when process.UOM = '2' then com_jobcard.total_stones
else 'something you want'
end as Total_qty
IF(condition, true_value, false_value) can be used this way
SELECT process.process_name, com_jobcard.job_card_num,
IF(process.UOM = '1', com_jobcard.dept_qty, IF(process.UOM = '2', com_jobcard.total_stones, 0)) AS Total_qty
FROM timer_completed
INNER JOIN PROCESS ON process.id = timer_completed.process_id
INNER JOIN com_jobcard ON timer_completed.job_card_id = com_jobcard.id
AND timer_completed.report_date = '2015-09-15'

How to create codeigniter query from below sql query?

I've a query like this which is working fine but I want to create a pure CI query from this. I'm new in CI so can anyone help me to figure out how this can be done or suggest me a reference website or link from where i can get help. Thanks
SELECT
user_des,
IFNULL((sent),0) as sent,
IFNULL((viewed),0) as viewed,
CONCAT(IFNULL(fname_usr,user_des),' ',lname_usr,user_des) as fullname,
IFNULL(sum(duration),0) as totalviewtime,
IFNULL((totalviews),0) as views,
IFNULL(sum(sharedcount),0) as shares,
IFNULL(sum(shared),0) as shared
FROM dem_senddemo
INNER JOIN
(SELECT * FROM dem_demos WHERE id_dem IN (746,943,748) AND customer_dem = '1') as demosfiltered
ON demo_des = id_dem
LEFT JOIN
(
(
Select senddemo_wis, sum(duration) as duration, max(datereceived_wis) as datereceived_wis
FROM
(
select senddemo_wis, invited_wis, sum(IFNULL(duration_fea,0) * IFNULL(percentviewed_wis,0)) as duration, max(datereceived_wis) as datereceived_wis
FROM (sta_views
LEFT JOIN sta_featureswisitavisits as s ON visit_fvi = id_vis
LEFT JOIN
(
(SELECT shortvideovid_fea as videoid_fea, shortvideoduration_fea as duration_fea
FROM dem_features
where shortvideoduration_fea > 0)
UNION
(SELECT longvideovid_fea as videoid_fea, longvideoduration_fea as duration_fea
FROM dem_features
where longvideoduration_fea > 0)
) as x
ON videoid_fea = showedvideo_fvi)
LEFT JOIN
sta_wistia as w ON invited_fvi = invited_wis AND s.showedvideo_fvi = w.mediaid_wis AND wistia_vis = email_wis
WHERE countvisit_wis <> 'N'
GROUP BY invited_wis
) as durfea
GROUP BY senddemo_wis
) UNION
(
SELECT senddemo_wis,sum(IFNULL(mainvideoduration_dem ,0) * IFNULL(percentviewed_wis,0)) as duration, max(datereceived_wis) as datereceived_wis
FROM sta_wistia as w
INNER JOIN
(select *, customer_dem as cuss FROM dem_demos) as demcorp ON demo_wis = id_dem AND mainmessagingvideovid_dem = w.mediaid_wis
LEFT JOIN sta_views ON email_wis = wistia_vis
WHERE customer_dem = 1 AND senddemo_wis > 0 AND countvisit_wis <> 'N'
GROUP BY senddemo_wis
)
) as c ON id_des = senddemo_wis
LEFT JOIN
(
SELECT user_des as user2_des, count(id_vis) as totalviews
FROM sta_views
LEFT JOIN dem_invited ON id_invited = invited_vis
LEFT JOIN dem_senddemo ON id_des = id_senddemo
WHERE NOT ISNULL(id_senddemo) AND countvisit_wis != 'N' AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND demo_des IN (746,943,748)
GROUP BY user_des
) as z ON user_des = user2_des
LEFT JOIN
(
SELECT user_des as user3_des, count(id_des) as sent
FROM dem_senddemo
LEFT JOIN dem_invited ON id_senddemo = id_des
WHERE createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND demo_des IN (746,943,748) AND first_invited = 'YES'
GROUP BY user_des
) as za ON user_des = user3_des
LEFT JOIN
(
SELECT user_des as user4_des, count(id_vis) as viewed
FROM sta_views LEFT JOIN dem_invited ON id_invited = invited_vis
LEFT JOIN dem_senddemo ON id_des = id_senddemo
WHERE NOT ISNULL(id_senddemo) AND countvisit_wis != 'N' AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND state = 'VIEWED'
AND first_invited = 'YES' AND demo_des IN (746,943,748)
GROUP BY user_des
) as zb ON user_des = user4_des
LEFT JOIN
(
SELECT id_senddemo as iddemdemos2, count(id_senddemo) as shared, allshares as sharedcount
FROM
(
SELECT id_senddemo, count(id_senddemo) as allshares
FROM dem_invited
LEFT JOIN dem_senddemo on id_senddemo = id_des
WHERE first_invited <> 'YES' AND demo_des IN (746,943,748)
GROUP BY id_senddemo
) as x
GROUP BY id_senddemo
) as zc ON iddemdemos2 = id_des
LEFT JOIN
sec_users ON user_des = id_usr
WHERE customer_dem = 1 AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59'
GROUP BY user_des

MySQL Rows Not being ignored

I have the result returning the way I want - I just want to ignore rows where MPG_VALUE > 30 (nvdtechnical.TECH_Value_Float)
But my query returns all - and unwanted rows have NULL in MPG_VALUE column.
How can I return only rows where MPG_VALUE > 30 ?
SELECT *, (SELECT PR_Basic + PR_VAT + PR_Delivery FROM nvdprices
WHERE PR_Id = capder.cder_ID ORDER BY PR_EffectiveTo ASC LIMIT 1) as P11D,
(SELECT nvdtechnical.TECH_Value_Float FROM nvdtechnical
WHERE TECH_TechCode = '11'
AND nvdtechnical.TECH_Id = capder.cder_ID
AND nvdtechnical.TECH_Value_Float > 30
LIMIT 1) as MPG_VALUE
from capmod
JOIN capder ON capder.cder_modcode = capmod.cmod_code
JOIN caprange ON capder.cder_rancode = caprange.cran_code
JOIN capman ON caprange.cran_mantextcode = capman.cman_code
JOIN nvdmodelyear ON capder.cder_ID = MY_Id
AND nvdmodelyear.MY_EffectiveTo = '0000-00-00 00:00:00'
JOIN nvdtechnical ON nvdtechnical.TECH_Id = capder.cder_ID
JOIN nvddictionarytechnical ON nvddictionarytechnical.DT_TechCode = nvdtechnical.TECH_TechCode
JOIN nvddictionarycategory ON nvddictionarycategory.DC_CatCode = nvddictionarytechnical.DT_CatCode
AND nvddictionarycategory.DC_CatCode=4
AND nvddictionarytechnical.DT_TechCode = 67
AND nvdtechnical.TECH_Value_Float >= '255'
JOIN capfueltype ON capfueltype.cft_code = capder.cder_fueltype
JOIN nvdbodystyle ON capmod.cmod_bodystyle = nvdbodystyle.bs_code
WHERE caprange.cran_mantextcode='140'
AND caprange.cran_code='522'
AND capder.cder_fueltype='P'
AND capder.cder_transmission='A'
AND nvdbodystyle.bs_code='3'
AND (cmod_discontinued=0 OR cmod_discontinued=2015)
AND capman.cman_code IN ('1','140','164')
AND caprange.cran_code IN ('924','126','147','955','965','661')
ORDER BY P11D, capman.cman_name ASC, caprange.cran_name, capmod.cmod_name
That is because you are doing a scalar query for the MPG Value. You are not really filtering which rows to show or hide, rather, you are showing all rows that has a value matched from your main query.
Imagine a left join, that is like what you are doing
SELECT nvdtechnical.TECH_Value_Float FROM nvdtechnical
WHERE TECH_TechCode = '11'
AND nvdtechnical.TECH_Id = capder.cder_ID
**AND nvdtechnical.TECH_Value_Float > 30**
LIMIT 1
to properly filter the data, you must filter in once more outside it in your where condition:
the easiest way would be like this one.
SELECT *
FROM (
SELECT *, (SELECT PR_Basic + PR_VAT + PR_Delivery FROM nvdprices
WHERE PR_Id = capder.cder_ID ORDER BY PR_EffectiveTo ASC LIMIT 1) as P11D,
(SELECT nvdtechnical.TECH_Value_Float FROM nvdtechnical
WHERE TECH_TechCode = '11'
AND nvdtechnical.TECH_Id = capder.cder_ID
AND nvdtechnical.TECH_Value_Float > 30
LIMIT 1) as **MPG_VALUE**
from capmod
JOIN capder ON capder.cder_modcode = capmod.cmod_code
JOIN caprange ON capder.cder_rancode = caprange.cran_code
JOIN capman ON caprange.cran_mantextcode = capman.cman_code
JOIN nvdmodelyear ON capder.cder_ID = MY_Id
AND nvdmodelyear.MY_EffectiveTo = '0000-00-00 00:00:00'
JOIN nvdtechnical ON nvdtechnical.TECH_Id = capder.cder_ID
JOIN nvddictionarytechnical ON nvddictionarytechnical.DT_TechCode = nvdtechnical.TECH_TechCode
JOIN nvddictionarycategory ON nvddictionarycategory.DC_CatCode = nvddictionarytechnical.DT_CatCode
AND nvddictionarycategory.DC_CatCode=4
AND nvddictionarytechnical.DT_TechCode = 67
AND nvdtechnical.TECH_Value_Float >= '255'
JOIN capfueltype ON capfueltype.cft_code = capder.cder_fueltype
JOIN nvdbodystyle ON capmod.cmod_bodystyle = nvdbodystyle.bs_code
WHERE caprange.cran_mantextcode='140'
AND caprange.cran_code='522'
AND capder.cder_fueltype='P'
AND capder.cder_transmission='A'
AND nvdbodystyle.bs_code='3'
AND (cmod_discontinued=0 OR cmod_discontinued=2015)
AND capman.cman_code IN ('1','140','164')
AND caprange.cran_code IN ('924','126','147','955','965','661')
ORDER BY P11D, capman.cman_name ASC, caprange.cran_name, capmod.cmod_name
) x
WHERE x.MPG_VALUE IS NOT NULL;
Note that the x.MPG_VALUE which is filtered outside is your scalar query.
Edit: You can try other methods like, inner join.
SELECT *, (SELECT PR_Basic + PR_VAT + PR_Delivery FROM nvdprices
WHERE PR_Id = capder.cder_ID ORDER BY PR_EffectiveTo ASC LIMIT 1) as P11D,
MPG_VALUE.TECH_Id
from capmod
JOIN capder ON capder.cder_modcode = capmod.cmod_code
JOIN caprange ON capder.cder_rancode = caprange.cran_code
JOIN capman ON caprange.cran_mantextcode = capman.cman_code
JOIN nvdmodelyear ON capder.cder_ID = MY_Id
AND nvdmodelyear.MY_EffectiveTo = '0000-00-00 00:00:00'
JOIN nvdtechnical ON nvdtechnical.TECH_Id = capder.cder_ID
JOIN nvddictionarytechnical ON nvddictionarytechnical.DT_TechCode = nvdtechnical.TECH_TechCode
JOIN nvddictionarycategory ON nvddictionarycategory.DC_CatCode = nvddictionarytechnical.DT_CatCode
AND nvddictionarycategory.DC_CatCode=4
AND nvddictionarytechnical.DT_TechCode = 67
AND nvdtechnical.TECH_Value_Float >= '255'
JOIN capfueltype ON capfueltype.cft_code = capder.cder_fueltype
JOIN nvdbodystyle ON capmod.cmod_bodystyle = nvdbodystyle.bs_code
INNER JOIN
(
SELECT TECH_Value_Float,TECH_Id
FROM nvdtechnical
WHERE TECH_TechCode = '11'
AND TECH_Value_Float > 30
) MPG_VALUE
ON MPG_VALUE.TECH_Id = capder.cder_ID
WHERE caprange.cran_mantextcode='140'
AND caprange.cran_code='522'
AND capder.cder_fueltype='P'
AND capder.cder_transmission='A'
AND nvdbodystyle.bs_code='3'
AND (cmod_discontinued=0 OR cmod_discontinued=2015)
AND capman.cman_code IN ('1','140','164')
AND caprange.cran_code IN ('924','126','147','955','965','661')
ORDER BY P11D, capman.cman_name ASC, caprange.cran_name, capmod.cmod_name;

How to optimize for speed a sql multiple select with SUM

I have a really long select from my database with many joins. The problem is with counting SUM: without sum, select time is about 3s, but with SUM is about 15s.
Is it possible to optimize my select to obtain a shorter select time?
Here is my code:
SELECT
accomodation.id,
accomodation.aid,
accomodation.title_en,
accomodation.title_url_en,
accomodation.address,
accomodation.zip,
accomodation.stars,
accomodation.picture,
accomodation.valid_from,
accomodation.valid_to,
accomodation.latitude,
accomodation.longitude,
accomodation.city_id AS
accomodation_city_id,
db_cities.id AS city_id,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_en AS country_title,
db_countries.title_url_en AS country_url,
accomodation_type.class AS accomodation_type_class,
accomodation_review_value_total.value AS review_total,
MIN(accomodation_price.price) AS price_from,
accomodation_rooms.total_persons
FROM
(SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
INNER JOIN accomodation
ON
accomodation_max.aid = accomodation.aid AND
accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities
ON (
db_cities.id = accomodation.city_id OR
(((acos(sin((db_cities.latitude*pi()/180)) * sin((accomodation.latitude*pi()/180)) + cos((db_cities.latitude*pi()/180)) * cos((accomodation.latitude*pi()/180)) * cos(((db_cities.longitude - accomodation.longitude)*pi()/180))))*180/pi())*60*1.1515*1.609344) < '20')
JOIN db_countries
ON db_countries.id = accomodation.country_id
LEFT JOIN accomodation_review_value_total
ON accomodation_review_value_total.accomodation_aid = accomodation.aid
LEFT JOIN accomodation_type_value
ON accomodation_type_value.accomodation_id = accomodation.id
LEFT JOIN accomodation_type
ON accomodation_type.id = accomodation_type_value.accomodation_type_id
JOIN accomodation_season
ON (
accomodation_season.accomodation_aid = accomodation.aid AND
( '2013-11-04' BETWEEN accomodation_season.start_date AND accomodation_season.end_date OR '2013-11-05' BETWEEN accomodation_season.start_date AND accomodation_season.end_date ) )
JOIN accomodation_price
ON
accomodation_price.accomodation_aid = accomodation.aid AND
accomodation_price.accomodation_price_type_id = '1' AND
accomodation_price.accomodation_price_cat_id = '1' AND
accomodation_price.price BETWEEN '20' AND '250' AND
accomodation_price.accomodation_season_id = accomodation_season.id
JOIN accomodation_theme_value
ON accomodation_theme_value.accomodation_id = accomodation.id
INNER JOIN
(SELECT
accomodation_id,
SUM(accomodation_rooms.rooms) AS total_rooms,
SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons
FROM accomodation_rooms
GROUP BY accomodation_id) accomodation_rooms
ON
accomodation_rooms.accomodation_id = accomodation.id AND
accomodation_rooms.total_persons >= '4'
WHERE
db_countries.title_url_en LIKE '%spain%' AND
db_cities.title_url LIKE '%barcelona%' AND
accomodation_type_value.accomodation_type_id IN (5,10) AND
total_rooms >= '2' AND
accomodation_theme_value.accomodation_theme_id IN (11,12,13) AND
accomodation.stars IN (3,4,5) AND
( accomodation_review_value_total.value >= '4.5' ) AND
db_cities.id = '2416'
GROUP BY accomodation.aid
ORDER BY
CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() AND MIN(accomodation_price.price) IS NOT NULL THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' AND MIN(accomodation_price.price) IS NOT NULL THEN 1
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() THEN 2
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' THEN 3
ELSE 4 END,
review_total DESC,
accomodation.title_en
LIMIT 10