Something wrong with my mySQL query - mysql

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.

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'

Is there any way to optimize this MySQL query when merging two query?

I was trying to get the result with product_id, stock, new_cost
SELECT inventory_logs.product_id, ROUND(SUM(inventory_logs.qty + 0), 4) AS stock
FROM products
JOIN inventory_logs on products.id = inventory_logs.product_id
WHERE inventory_logs.`type` = 'as'
AND inventory_logs.`created_at` between '1970-01-01' and '2021-02-22 23:59:59'
AND inventory_logs.`branch_id` = 1
AND inventory_logs.`deleted_at` IS NULL AND products.deleted_at IS NULL
GROUP BY inventory_logs.product_id HAVING stock > 0
above that is the query for getting stock,
duration for query is about 0.031 sec
SELECT inventory_logs.product_id, inventory_logs.new_cost
FROM inventory_logs JOIN(
SELECT product_id, MAX(created_at) AS created_at
FROM inventory_logs
WHERE created_at <= '2021-02-22 23:59:59' AND deleted_at IS NULL
AND `type` = 'as'
AND inventory_logs.`branch_id` = 1
GROUP BY product_id
) i2 ON (inventory_logs.product_id = i2.product_id AND inventory_logs.created_at = i2.created_at)
WHERE `type` = 'as'
AND inventory_logs.`branch_id` = 1
above is the query for getting new_cost, duration for query is also about 0.031 sec
But when I try to merge the above two query into one, the duration of query is 26.016 sec
The query is
SELECT inventory_logs.product_id, ROUND(SUM(inventory_logs.qty = 0), 4) AS stock, sub.new_cost
FROM products
JOIN inventory_logs ON products.id = inventory_logs.product_id
JOIN (
SELECT inventory_logs.product_id, inventory_logs.new_cost
FROM inventory_logs JOIN (
SELECT product_id, MAX(created_at) AS created_at
FROM inventory_logs
WHERE created_at <= '2021-02-22 23:59:59' AND deleted_at IS NULL
AND `type` = 'as'
AND inventory_logs.`branch_id` = 1
GROUP BY product_id
) i2 ON (inventory_logs.product_id = i2.product_id AND inventory_logs.vreated_at
= i2.created_at)
WHERE `type` = 'as'
AND inventory_logs.`branch_id` = 1
) sub ON products.id = sub.product_id
WHERE inventory_logs.`type` = 'as'
AND inventory_logs.`created_at` BETWEEN '1970-01-01' AND '2021-02-22 23:59:59'
AND inventory_logs.`branch_id` = 1
AND inventory_logs.`deleted_at` IS NULL
AND products.deleted_at IS NULL
GROUP BY inventory_logs.product_id HAVING stock > 0
Is there any ways to optimize the above query to make it take lesser time?

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`;

What is wrong is this mysql statement with case?

SELECT COUNT(*)
FROM PATIENTS A, RECALLS_AFTER_RESERV C
LEFT JOIN PATIENT_LAST_RESERV D
ON D.PATIENT_ID = C.PATIENT_ID
WHERE C.PATIENT_ID = A.ID
AND C.OFFICE_ID = A.OFFICE_ID
AND C.OFFICE_ID = ?
AND YEAR(CONVERT_TZ(C.RECALLS_AT, 'UTC', 'Asia/Tokyo')) = ?
AND (CASE
WHEN ISNULL(D.STARTS_AT) THEN
A.CHECKED_IN_AT
ELSE
D.STARTS_AT
END) >= CONVERT_TZ('2015-01-27 00:00:00', 'Asia/Tokyo', 'UTC')) AND (CASE
WHEN ISNULL(D.STARTS_AT) THEN
A.CHECKED_IN_AT
ELSE
D.STARTS_AT
END) <= CONVERT_TZ('2015-01-27 23:59:59', 'Asia/Tokyo', 'UTC') AND C.RECALLED_AT IS NULL AND C.STARTS_AT IS NULL
I want to use the case to determine whether the D.starts_at have value,if not, I use A.checked_in_at to replace the D.starts_at.but it gives an error
(case when isnull(D.starts_at) then A.checked_in_at else D.starts_at end) >= CONVERT_TZ('2015-01-27 00:00:00', 'Asia/Tokyo', 'UTC') )
I finally find the problem, the case statement is right. the problem is the redundant ) in the above.

Mysql optimization operator 'I N'

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'