Mysql optimization operator 'I N' - mysql

I have this query.
I want to optimization this query,because it takes more then 4.sec
![SELECT clerk_id, COUNT(*) AS num
FROM `note`
WHERE note.id IN (
SELECT note.id
FROM `note`
LEFT JOIN conn ON conn.contract_id = note.id
WHERE `type` <>4 AND `type` <>6 AND `cancelled` =0 AND `ebill` <> '' AND activated_datetime > '0000-00-00 00:00:00' AND activated_datetime >= '2011-06-13 00:00:00' AND activated_datetime <= '2011-06-21 23:59:59' AND clerk_code LIKE 'S%'
)
GROUP BY clerk_id][1]
Thanks for suggestions

I think you could write your query as a single one like this:
SELECT clerk_id, COUNT(*)
FROM `contracts`
LEFT JOIN contract_connections ON contract_connections.contract_id = contracts.id
WHERE `type` <>4 AND `type` <>6 AND `cancelled` =0 AND `ebill` <> '' AND activated_datetime >= '2011-06-13 00:00:00' AND activated_datetime <= '2011-06-21 23:59:59' AND clerk_code LIKE 'S%' GROUP BY clerk_id
Please check and see if it returns the same thing and if performance improves

SELECT clerk_id, COUNT(*) AS num
FROM `contracts`
WHERE EXISTS (
SELECT *
FROM contract_connections
WHERE `type` <>4 AND `type` <>6 AND `cancelled` =0 AND `ebill` <> '' AND activated_datetime >= '2011-06-13 00:00:00' AND activated_datetime <= '2011-06-21 23:59:59' AND clerk_code LIKE 'S%'
AND contract_connections ON contract_connections.contract_id = contracts.id
)
GROUP BY clerk_id
In case you have an index on the type column you could benefit from it changing your WHERE clause from
WHERE type <>4 AND type <>6
To
WHERE (type<4 OR type=5 OR type>6)
Also remove
activated_datetime > '0000-00-00 00:00:00'
Since you already have
activated_datetime >= '2011-06-13 00:00:00'

Related

Select Between 2 dates but also select NULL values

I'm trying to run a query where I select dates between 2 values
OR ( `order_products`.`deleted_at` BETWEEN
'2021-01-01 00:00:00' AND '2021-07-28 23:59:59' )
But I also need to collect order_products with NULL values.
Is this at all possible, as when I put an
OR `order_products`.`deleted_at` IS NULL
Into my code, It seems to just return absolutley everything in the database :-(
My current code, for context is :
SELECT
`orders`.`id`,
`orders`.`reference`,
`orders`.`order_date`,
`orders`.`cancellation_date`,
`order_products`.`description`,
`order_products`.`st_code`,
`order_products`.`supplier_stock_code`,
`order_products`.`status`,
`order_products`.`deleted_at`,
`supplier`.`name`,
order_invoice.created_at AS credit_date,
fitters.account_number AS fitter_account_number,
fitters.name AS fitter
FROM `order_products`
LEFT JOIN `orders` ON (`orders`.`id` = `order_products`.`order_id`)
LEFT JOIN `supplier` ON (`order_products`.`supplier_id` = `supplier`.`id`)
LEFT JOIN `fitters` ON (`orders`.`fitter_id` = `fitters`.`id`)
JOIN `order_invoice` ON (`order_invoice`.`order_id` = `orders`.`id`)
WHERE `cancellation_date` IS null
AND `cancellation_date` BETWEEN '2021-01-01 00:00:00' AND '2021-07-28 23:59:59'
AND `order_invoice`.`status` = 'approved'
OR (`order_products`.`deleted_at` BETWEEN '2021-01-01 00:00:00'
OR `order_products`.`deleted_at` IS NULL
AND '2021-07-28 23:59:59')
AND `order_products`.`product_type` = 'product'
ORDER BY `orders`.`id` ASC
Your syntax is off. You need:
WHERE order_products.deleted_at >= '2021-01-01' AND
order_products.deleted_at < '2021-07-29' OR
order_products.deleted_at IS NULL
Note that I wrote the datetime check using date inequalities, which seems cleaner to me. Also, we don't need any extra parentheses here as AND has higher precedence than OR.
Please try changing the where condition to
WHERE cancellation_date IS null
AND cancellation_date BETWEEN '2021-01-01 00:00:00' AND '2021-07-28 23:59:59'
AND order_invoice.status = 'approved'
OR (order_products.deleted_at IS NULL OR order_products.deleted_at BETWEEN '2021-01-01 00:00:00' AND '2021-07-28 23:59:59')
AND order_products.product_type = 'product'

SQL Query - adding max condition for distinct name

Warmest thanks by advance for your help
My current SQL query :
SELECT
`id`,
`comp`,
`jour`,
`hippo`,
`numcourse`,
`cl`,
`dist`,
`partant`,
`typec`,
`cheque`,
`numero`,
`cheval`,
`age`,
`cotedirect`
FROM `turf_12dec`.`cachedate` c
WHERE
`partant` > '7'
AND `typec` = 'Attelé'
AND `jour` > '2017-01-01'
AND `cl` != ''
AND `cl`!= 'NP'
That I wish :
AND max(jour) for distinct cheval is > '2019-01-01'
This query:
SELECT `cheval`
FROM `turf_12dec`.`cachedate`
GROUP BY `cheval`
HAVING MAX(`jour`) > '2019-01-01'
returns all the chevals that you describe in your condition and you can join it to the table:
SELECT t.`id`, t.`comp`, t.`jour`, t.`hippo`, t.`numcourse`, t.`cl`,
t.`dist`, t.`partant`, t.`typec`, t.`cheque`, t.`numero`,
t.`cheval`, t.`age`, t.`cotedirect`
FROM `turf_12dec`.`cachedate` t INNER JOIN (
SELECT `cheval`
FROM `turf_12dec`.`cachedate`
GROUP BY `cheval`
HAVING MAX(`jour`) > '2019-01-01'
) tt ON tt.`cheval` = t.`cheval`
WHERE t.`partant` > '7' and
t.`typec` = 'Attelé' and
t.`jour` > '2017-01-01' and
t.`cl` != '' AND
t.`cl`!= 'NP'
You can add a correlated subquery:
and exists (select 1
from `turf_12dec`.`cachedate` cd
where cd.cheval = cachedate.cheval and cd.jour > '2019-01-01'
)
You don't mention the additional filtering conditions. You may need to repeat them in the subquery as well, if they should also apply to the maximum jour.
You could add an additional filter with a correlated subquery:
SELECT
`id`,
`comp`,
`jour`,
`hippo`,
`numcourse`,
`cl`,
`dist`,
`partant`,
`typec`,
`cheque`,
`numero`,
`cheval`,
`age`,
`cotedirect`
FROM `turf_12dec`.`cachedate` c
WHERE
`partant` > '7'
AND `typec` = 'Attelé'
AND `jour` > '2017-01-01'
AND `cl` != ''
AND `cl`!= 'NP'
AND (
SELECT MAX(`jour`)
FROM `turf_12dec`.`cachedate` c1
WHERE c1.`cheval` = c.`cheval`
) > '2019-01-01'
This can also be expressed with an EXITS condition:
AND EXISTS (
SELECT 1
FROM `turf_12dec`.`cachedate`
WHERE c1.`cheval` = c.`cheval` AND `jour` > '2019-01-01'
)

MySQL query hanging

I have a mysql query, which runs however it just hangs and doesn't stop. I'm unsure where the query is breaking.
SELECT
TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', f.Datestamp) AS Epoch,
f.value AS `Usage`,
q.Name AS Quantity,
q.QuantityID,
units,
PrimeDataItem,
dd.Description
FROM SourceChannels c
JOIN UsageHhourly f ON c.ChanID = f.ChanID
JOIN Quantities q ON c.QuantityID = q.QuantityID
LEFT JOIN DigitalDescriptions dd ON ((c.DigitalDescriptionID = dd.DigitalDescriptionID)
AND f.value = (CASE WHEN dd.Value REGEXP '^[0-9]' = 1 then dd.Value ELSE -1 END))
WHERE
c.EquipmentID = 1496
AND f.DateStamp >= '2016-12-28 00:00:00'
AND f.DateStamp < '2017-01-04 00:00:00'
ORDER BY q.QuantityID, f.datestamp
The question does not provide more en-lighting information. Try to alter your query like in the below example.
SELECT
TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', `f`.`Datestamp`) AS `Epoch`,
`f`.`value` AS `Usage`,
`q`.`Name` AS `Quantity`,
`q`.`QuantityID`,
`c`.`units`,
`c`.`PrimeDataItem`,
`dd`.`Description`
FROM `SourceChannels` `c`
INNER JOIN `UsageHhourly` `f` ON `c`.`ChanID` = `f`.`ChanID`
INNER JOIN `Quantities` `q` ON `c`.`QuantityID` = `q`.`QuantityID`
LEFT JOIN `DigitalDescriptions` `dd` ON `c`.`DigitalDescriptionID` = `dd`.`DigitalDescriptionID`
WHERE
`f`.`value` = IF((dd.Value REGEXP '^[0-9]'),1,-1)
AND `c`.`EquipmentID` = 1496
AND `f`.`DateStamp` BETWEEN '2016-12-28 00:00:00' AND '2017-01-04 00:00:00'
ORDER BY `q`.`QuantityID`, `f`.`datestamp`;

Passing column in subquery is not working

Please take a look at my query
SELECT ht_tutor.id
,(
SELECT group_concate(days)
FROM (
SELECT fkTutorId
,days
,(
CASE
WHEN endTime <= '14:00:00'
THEN '00:00:00'
WHEN TIMEDIFF(startTime, '14:00:00') < '00:00:00' && TIMEDIFF('17:00:00', endTime) < '00:00:00'
THEN TIMEDIFF('17:00:00', '14:00:00')
ELSE '00:00:00'
END
) AS intersect_time
FROM ht_tutorAvailablity
WHERE ht_tutorAvailablity.fkTutorId = ht_tutor.id
) AS avail_table
) AS days_avail
FROM ht_tutor
LIMIT 0,10
ERROR: #1054 - Unknown column 'ht_tutor.id' in 'where clause'
How can I pass ht_tutor.id their ?
If I'm passing tutor_id manually like ht_tutorAvailablity.fkTutorId = "12" than it is working fine.
Hope you need to use JOIN in your scenario. The below query will JOIN with the TUT.id = AVA.fkTutorId condition:
SELECT group_concate(days), id
FROM (
SELECT AVA.fkTutorId, AVA.days, TUT.id
CASE
WHEN AVA.endTime <= '14:00:00'
THEN '00:00:00'
WHEN TIMEDIFF(AVA.startTime, '14:00:00') < '00:00:00' && TIMEDIFF('17:00:00', AVA.endTime) < '00:00:00'
THEN TIMEDIFF('17:00:00', '14:00:00')
ELSE '00:00:00'
END AS intersect_time
FROM ht_tutorAvailablity AVA
JOIN ht_tutor TUT ON TUT.id = AVA.fkTutorId
) AS avail_table
LIMIT 0, 10

Something wrong with my mySQL query

SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
Basically it's ignoring the t.off part, whats wrong?
Thank you =)
(the query was edited for an example purpose, the real query is similar to this but with other table names, etc)
== [ Update ] ==
SELECT t.active, t.off, t.duration, t.user
FROM table t
WHERE (
t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
)
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
UNION ALL
SELECT c.active, c.off, c.duration, c.user
FROM chair c
WHERE (
c.active = '0000-00-00 00:00:00'
OR c.duration != '0'
)
AND c.user = '1'
AND c.off = '0000-00-00 00:00:00'
You should use parenthesis, to group conditions (and / or), to make sure they are evaluated in the order you want.
For example, do you want to following :
SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE t.active = '0000-00-00 00:00:00'
OR (
t.duration != '0'
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
)
LIMIT 0 , 30
Or the following :
SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE (
t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
)
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
Or maybe something else ?
Using parenthesis will make your query easier to read -- and will help making sure the conditions are evaluated properly.