Mysql-cast and convert in joins is not working - mysql

In a MySQL table, they have stored return_time as VARCHAR(20) and return_date as a date field. Now I have to compare this based on the given date and time and produce the result. For example, records save in the time column will be like '10:00 PM', '11:00 PM', '02:00 AM' etc and in the date column like '2021-02-02', '2021-01-02' etc
I combined the return_dateand return_time, and compare it with the given date and time like
SELECT *
FROM `travel_infos` as TravelInfo
WHERE TravelInfo.travel_status = 'Open' AND
cast(concat(TravelInfo.return_date, ' ', STR_TO_DATE(TravelInfo.return_time, '%l:%i %p' )) as datetime) > '2021-03-03 14:03'
It outputs me 231 records. travel_infos table has 700 records.
Then I do the join without considering the return_time column
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND TravelInfo.id!=0
AND Part.part_type IN('Charter') AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND TravelInfo.return_date >= '2021-03-03 14:03'
AND Part.is_delete=0
It outputs me 175 records.
So now I want to join by considering both return_date and return_time. So I tried like
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND
TravelInfo.id!=0
AND Part.part_type IN('Charter')
AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND (cast(concat(TravelInfo.return_date, ' ',
STR_TO_DATE(TravelInfo.return_time, '%l:%i %p' )) as datetime)) >= '2021-03-03 14:03' AND Part.is_delete=0
This outputs me 0 records. What went wrong in the 3rd SQL query? Both 1st and 2nd produce the output.
In my 3rd query, I modified the 2nd query WHERE like in the 1st query.
Can someone help me to solve this thank you.

Convert both dates you are comparing to datetimes in the where clause:
SELECT Part.*,TravelInfo.*,Category.*,Buttons.*
FROM travel_infos As TravelInfo
LEFT JOIN parts as Part ON Part.id = TravelInfo.part_id_1
LEFT JOIN buttons as Buttons ON Part.button_name_id= Buttons.id
LEFT JOIN categories as Category ON Part.category_id = Category.id
WHERE Part.id != 0 AND
TravelInfo.id!=0
AND Part.part_type IN('Charter')
AND Part.store_id='1'
AND TravelInfo.travel_status = 'Open'
AND TravelInfo.return_date >= STR_TO_DATE('2021-03-03', '%Y-%m-%d')
AND cast(TravelInfo.return_time as time) >= cast('14:03:00' as time)
AND Part.is_delete=0

Related

MySQL - Joining same table twice, parent sum column value getting duplicated

I'm just 3 months of experience in MySQL. Here I'm trying to generate a report based on log and part table. When trying to join the "Part" table twice, the "Log" table Quantity gets doubled. Kindly let me know where I'm doing wrong.
Log Table
Part Table
Expected Report
Query Used
SELECT
report.*,
(SUM(report.quantity)) AS totalQuantity,
normalPart.price AS normalPrice,
premiumPart.price AS premiumPrice
FROM
log AS report
LEFT JOIN
(SELECT
*
FROM
part AS normalPart
WHERE
normalPart.type = 'normal'
GROUP BY normalPart.partNumber , normalPart.genId) AS normalPart ON report.partNumber = normalPart.partNumber
AND report.genId = normalPart.genId
AND normalPart.cat = report.fromCat
LEFT JOIN
(SELECT
*
FROM
part AS premiumPart
WHERE
premiumPart.type = 'premium'
GROUP BY premiumPart.partNumber , premiumPart.genId) AS premiumPart ON report.partNumber = premiumPart.partNumber
AND report.genId = premiumPart.genId
AND premiumPart.cat = report.toCat;
Query Result
This answers the original version of the question.
Aggregate before you join:
select l.*, p.normal_price, p.premium_price
from (select genid, partnumber, sum(quantity) as quantity
from log
group by genid, partnumber
) l left join
(select partnumber, genid,
max(case when type = 'normal' then price end) as normal_price,
max(case when type = 'premium' then price end) as premium_price
from part
group by partnumber, genid
) p
on p.partnumber = l.partnumber and p.genid = l.genid

MYSQL - JOIN table filter not working

I have four table each table connected with some id kindly see the below query how I'm getting
SELECT
tax_rates.name,
IF( products.tax_method = 0, 'Inclusive', 'Exclusive') AS type,
IF((SUM(purchases.grand_total) > 0),(SUM(purchases.grand_total)),(SUM(purchase_items .subtotal))) AS total_amount,
IF((SUM(purchases.order_tax) > 0),(SUM(purchases.order_tax)),SUM(purchase_items .item_tax)) AS tax_amount
FROM tax_rates
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id
LEFT JOIN purchase_items ON purchase_items.tax_rate_id = tax_rates .id
LEFT JOIN products ON products.id = purchase_items.product_id
WHERE purchases.warehouse_id = 1
GROUP BY tax_rates.id, products.tax_method
ORDER BY tax_rates.name desc LIMIT 0, 10
The above query didn't return any result but if I remove WHERE purchases.warehouse_id = 1 then it display the result. I don't know where I'm doing the mistake. Kindly correct me.
Sorry to tell about this I'm try to get purchase order tax and purchase Item tax
in particular store and date
Output
name type total_amount tax_amount
VAT #20% Inclusive 11005.2000 1834.2000
VAT #10% Inclusive 165.0000 15.0000
No Tax Exclusive 204771.4000 0.0000
GST #6% Exclusive 7155.0000 405.0000
GST #6% Inclusive 7155.0000 405.0000
Thank you
Data type? purchases.warehouse_id = '1'?
You should not add the condition in where clause, when you are using the field of the left join table. so remove the where clause and use like below
LEFT JOIN purchases ON purchases.order_tax_id = tax_rates.id and purchases.warehouse_id = 1
If you try to add the left join table field in where clause it will become INNER JOIN. hence it may not display any rows according to your data.

Formatting left join in mysql select( Not showing all records in left table)

I have following sql
SELECT *
FROM (SELECT sample_register.usin,
Date_format(sample_register.doc, '%d-%m-%Y') AS doc1,
sample_register.location,
sample_register.description,
gamma_results.act,
gamma_results.act_sd,
gamma_results.mdl,
gamma_results.bdl
FROM sample_register
LEFT JOIN gamma_results
ON gamma_results.usin = sample_register.usin
WHERE Mid(sample_register.usin, 3, 1) = 'F'
AND sample_register.doc BETWEEN'2014-09-01' AND '2014-09-26'
AND sample_register.type <> 'WATER'
AND gamma_results.istp = 'Cs137'
ORDER BY Mid(sample_register.usin, 3, 1),
sample_register.doc,
sample_register.usin) AS a
LEFT JOIN (SELECT sample_register.usin,
gamma_results.act,
gamma_results.act_sd,
gamma_results.mdl,
gamma_results.bdl
FROM sample_register
LEFT JOIN gamma_results
ON gamma_results.usin = sample_register.usin
WHERE Mid(sample_register.usin, 3, 1) = 'F'
AND sample_register.doc BETWEEN
'2014-09-01' AND '2014-09-26'
AND ( sample_register.type <> 'WATER' )
AND gamma_results.istp = 'k40'
ORDER BY Mid(sample_register.usin, 3, 1),
sample_register.doc,
sample_register.usin) AS b
ON a.usin = b.usi
It gives me only 2 rows . There are 30 records meeting the where clause in sample_register and 4 records corresponding to 2 USIN in gamma_results. I want all the 30 records in sample_register joined with gamma_results, where data is available for only 2 USINs. Remaining 28 records in sample_register, the returned field values can be null. I found that if I am removing the condition gamma_results_istp then all the 30 records are shown. But I do not want this. Any suggestions please .
Not sure but probably that you must transfert the condition gamma_results_istp from the Where operator to the ON operator; otherwise it is applied after the Left Join has been performed, not before:
... On (gamma_results.usin = sample_register.usin and gamma_results.istp='Cs137')
Repeat the same for your second gamma_results.istp condition.
Also, simplifying your example in order to show us only what's relevant wouldn't have hurt anyone.

length of mysql result

I made this query and i cant figure out why number of characters in chal_rews.rewards field on line 37 returns exactly 341 characters where there are more than 400 characters.
SELECT
GROUP_CONCAT( users.email ) AS group_emails,
GROUP_CONCAT(
CONCAT(
IFNULL(users.first_name,users.email),' ',IFNULL(users.last_name,''),'|',
IFNULL(users.facebook_id,''),'|',
IFNULL(users.email,''),'|',
users.id,'|',
invitations.wined,'|',
invitations.accepted,'|',
invitations.id
)
) AS participants,
owner.id AS owner_id,
owner.email,
owner.facebook_id,
owner.access_token,
owner.first_name,
CONCAT( IFNULL(owner.first_name,owner.email),' ',IFNULL(owner.last_name,'') ) AS owner_fullname,
challenges.id AS challenge_id,
challenges.challenge_type_id,
challenges.period_id,
challenges.period_amount,
challenges.category_item_id,
challenges.metric_amount,
challenges.owner_user_id,
CASE
WHEN challenges.status=2 THEN 'complete'
WHEN ( challenges.status=1 AND challenges.end_date<NOW() ) THEN 'waiting_for_winner'
ELSE challenges.status
END AS status,
DATE_FORMAT(challenges.start_date,'%d %M %Y # %H:%i') AS start_date,
DATE_FORMAT(challenges.end_date,'%d %M %Y # %H:%i') AS end_date,
DATE_FORMAT(challenges.created_at,'%d %M %Y # %H:%i') AS created_at,
DATE_FORMAT(challenges.updated_at,'%d %M %Y # %H:%i') AS updated_at,
challenges.inform,
chal_rews.rewards,
chal_rews.reward_names AS reward_name,
category_items.item_name,
LOWER( CONCAT(fixed_verb,' ',IF(metric_amount=-1,'',CONCAT(metric_amount,' ')),fixed_metric,' ',fixed_text,' ',challenges.period_amount ,' ',periods.name) ) AS challenge_string
FROM
invitations
Left Join users ON invitations.user_id = users.id
Left Join challenges ON invitations.challenge_id = challenges.id
Left Join users AS owner ON owner.id = challenges.owner_user_id
Left Join challenge_types ON challenges.challenge_type_id = challenge_types.id
Left Join periods ON challenges.period_id = periods.id
Left Join category_items ON challenges.category_item_id = category_items.id
Left Join (
SELECT
chal_rews.id,
chal_rews.challenge_id,
chal_rews.reward_item_id,
chal_rews.user_id,
chal_rews.created_at,
chal_rews.updated_at,
GROUP_CONCAT(CONCAT(
IFNULL(users.first_name,users.email),' ',IFNULL(users.last_name,''),'|',
IFNULL(users.facebook_id,''),'|',
IFNULL(users.access_token,''),'|',
IFNULL(users.email,''),'|',
users.id,'|',
IFNULL(chal_rews.id,' '),'|',
IFNULL(chal_rews.reward_item_id,' '),'|',
IFNULL(reward_items.name,' ')
)) AS rewards,
GROUP_CONCAT(reward_items.name) AS reward_names
FROM
chal_rews
Left Join users ON users.id = chal_rews.user_id
Left Join reward_items ON reward_items.id = chal_rews.reward_item_id
GROUP BY
chal_rews.challenge_id
) AS chal_rews ON challenges.id = chal_rews.challenge_id
WHERE 1=1
while if i run only this part of query then rewards field returns exactly what it should i.e. full concatenated string.
SELECT
chal_rews.id,
chal_rews.challenge_id,
chal_rews.reward_item_id,
chal_rews.user_id,
chal_rews.created_at,
chal_rews.updated_at,
GROUP_CONCAT(CONCAT(
IFNULL(users.first_name,users.email),' ',IFNULL(users.last_name,''),'|',
IFNULL(users.facebook_id,''),'|',
IFNULL(users.access_token,''),'|',
IFNULL(users.email,''),'|',
users.id,'|',
IFNULL(chal_rews.id,' '),'|',
IFNULL(chal_rews.reward_item_id,' '),'|',
IFNULL(reward_items.name,' ')
)) AS rewards,
GROUP_CONCAT(reward_items.name) AS reward_names
FROM
chal_rews
Left Join users ON users.id = chal_rews.user_id
Left Join reward_items ON reward_items.id = chal_rews.reward_item_id
GROUP BY
chal_rews.challenge_id
I cant figure out what is wrong. SOS plz...
Bit of a punt this but it might help. If it doesn't then, well, sorry! You might get some joy by tightening up the group by clause at the end of the chal_rews sub-select. Hence:
SELECT
chal_rews.id,
chal_rews.challenge_id,
chal_rews.reward_item_id,
chal_rews.user_id,
chal_rews.created_at,
chal_rews.updated_at,
GROUP_CONCAT(CONCAT(
IFNULL(users.first_name,users.email),' ',IFNULL(users.last_name,''),'|',
IFNULL(users.facebook_id,''),'|',
IFNULL(users.access_token,''),'|',
IFNULL(users.email,''),'|',
users.id,'|',
IFNULL(chal_rews.id,' '),'|',
IFNULL(chal_rews.reward_item_id,' '),'|',
IFNULL(reward_items.name,' ')
)) AS rewards,
GROUP_CONCAT(reward_items.name) AS reward_names
FROM
chal_rews
Left Join users ON users.id = chal_rews.user_id
Left Join reward_items ON reward_items.id = chal_rews.reward_item_id
GROUP BY
chal_rews.id,
chal_rews.challenge_id,
chal_rews.reward_item_id,
chal_rews.user_id,
chal_rews.created_at,
chal_rews.updated_at
It's a little tricky to be sure without the actual tables and data in front of me but I think you will get a more consistent result in the rewards field if you do this. I think the columns that are coming back in the sub-select are inconsistent when you run it as part of the main query compared to when you run it in isolation. I suspect this is being caused by letting MySQL 'choose' a value for the chal_rews.user_id and chal_rews.reward_item_id (which in turn are used to outer join onto the users and reward_items tables - hence bringing back inconsistent data). More formally I reckon you are getting an indeterminate results set when excluding non-aggregated columns from the GROUP BY that are present in the SELECT.
Good luck and post how you get on!

count multiple in one statement

i have a table with data title and date of the data inserted.
and right now i want to do count to make the statistic out of it.
can i do multiple count in one sql statement?
like from, the column date, i want to count how many on this month, and how many in this year, until month selected. is it possible? if yes, how?
this is what i have come up, for now.
SELECT a.trigger_type_code
, c.trigger_name
, COUNT(*) AS number
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011'
GROUP BY trigger_type_code,trigger_name
by this is only for one count.help.:(
You could use a case:
select sum(case when MONTH(b.created_date) = '05'
AND YEAR(b.created_date) = '2011' then 1 end) as Count_2011_05
, sum(case when YEAR(b.created_date) = '2011'
then 1 end) as Count_2011
from ... etc ...
I think you could go like this:
SELECT
a.trigger_type_code,
c.trigger_name,
COUNT(MONTH(b.created_date) < 5 OR NULL) AS before_the_month,
COUNT(MONTH(b.created_date) = 5 OR NULL) AS in_the_month
FROM issue_trigger a
INNER JOIN cs_issue b
ON b.issue_id = a.issue_id
INNER JOIN ref_trigger_type c
ON c.trigger_type_code = a.trigger_type_code
WHERE YEAR(b.created_date) = 2011
GROUP BY a.trigger_type_code, c.trigger_name