So I have this query:
SELECT
AED.aId, CJ.*
FROM
AED
LEFT JOIN
Cronjob as CJ
ON CJ.aID = AED.aId
WHERE
AED.aStatus = '1'
AND
(
CJ.cjDatum < CURRENT_DATE - INTERVAL 14 DAY
AND
AED.aRegistratie > CURRENT_DATE - INTERVAL 10 YEAR
)
OR
(
CJ.cjStatus = '9'
OR
CJ.cjStatus = '2'
)
The problem is, the Cronjob table is empty, and if it's empty is still want to give all the Id's from AED with the status 1
I couldn't find anything use full, so I hope you guys can help!
You should move all the CJ criteria into the join's ON clause.
ON (
CJ.aID = AED.aId
AND (cjStatus in ('2','9') OR cjDatum < CURRENT_DATE - INTERVAL 14 DAY ))
Option two would be to leave them in WHERE, but make provisions for the case that cjStatus and friends are NULL (which they will be if no match is found).
OR cjStatus IS NULL
When there is no CronJob associated, the filter CJ.cjStatus = '9' (for example) return false, since CJ.cjStatus is null. That's what a LEFT JOIN do, it returns null field when there is no correspondance.
To add filter on the table you want to LEFT JOIN with, the filter clause must be in the join clauses like this:
SELECT AED.aId
, CJ.*
FROM AED
LEFT JOIN Cronjob as CJ
ON CJ.aID = AED.aId
AND (CJ.cjDatum < CURRENT_DATE - INTERVAL 14 DAY
AND AED.aRegistratie > CURRENT_DATE - INTERVAL 10 YEAR
)
OR (CJ.cjStatus = '9' OR CJ.cjStatus = '2')
WHERE AED.aStatus = '1'
Add OR (CJ.aid is null) to your AND part of condition:
SELECT
AED.aId, CJ.*
FROM
AED
LEFT JOIN
Cronjob as CJ
ON CJ.aID = AED.aId
WHERE
AED.aStatus = '1'
AND
(
(
CJ.cjDatum < CURRENT_DATE - INTERVAL 14 DAY
AND
AED.aRegistratie > CURRENT_DATE - INTERVAL 10 YEAR
)
OR (CJ.aid is null)
)
OR
(
CJ.cjStatus = '9'
OR
CJ.cjStatus = '2'
)
Related
SELECT MAX(r.endTime) as maxETime,r.vehicleId,v.emixis_id
FROM reservation r , vehicle v
WHERE r.vehicleId = v.vehicleId AND
r.workingDay = CURRENT_DATE() AND
r.isNote=0 AND
r.isDeleted=0 AND
r.status NOT IN("cancelled") AND
DATE_FORMAT(NOW(),'%H:%i:%s') > DATE_SUB(MAX(r.endTime), INTERVAL 1 HOUR)
GROUP BY r.vehicleId;
This is my code, what want to do is get MAX(r.endTime) value in to DATE_SUB. MAX not working with where condition, is there way to do this kind of thing ? I tried with #var:=MAX(r.endTime) and set it inside DATE_SUB, but #var always store last row's value.
SELECT MAX(r.`endTime`) as `maxETime`,r.`vehicleId`,v.`emixis_id`
FROM `reservation` r , `vehicle` v
WHERE r.`vehicleId` = v.`vehicleId` AND
r.`workingDay` = CURRENT_DATE() AND
r.`isNote`=0 AND
r.`isDeleted`=0 AND
r.`status` NOT IN("cancelled")
GROUP BY r.`vehicleId`
HAVING DATE_FORMAT(NOW(),'%H:%i:%s') > DATE_ADD(MAX(r.`endTime`), INTERVAL 1 HOUR)
I have a query that selects 3 random items from database table but I need to apply some more logic to the query based on the value of a field in the query.
This is what I have so far hope it makes sense. Have not fully tested it yet figured I would run it through you guys first see if there is anything that jumps out.
SELECT ord.id, keyword, url, daily_max
FROM orders AS ord
LEFT JOIN product_tasks AS tsk ON tsk.id = ord.task_id
LEFT JOIN product_groups AS grp ON grp.id = tsk.product_group
WHERE (
status = 'approved' AND
ord.total_actions_today < tsk.daily_max AND
grp.id = 1 AND
country_code = '$country' AND
(
CASE WHEN daily_max >= 5 THEN last_displayed < (NOW() - INTERVAL 30 MINUTE)
CASE WHEN daily_max >10 THEN last_displayed < (NOW() - INTERAVAL 5 MINUTE)
ELSE last_displayed < (NOW() - INTERAVAL 60 MINUTE)
)
)
GROUP BY ord.id
ORDER BY RAND()
LIMIT 3
Just tested the query and as I suspected I have my syntax wrong so any help would be appreciated:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASE WHEN daily_max >10 THEN last_displayed < (NOW() - INTERAVAL 5 MINUTE) ' at line 14
Edit - Fixed
(After several attempts + edits):
SELECT ord.id, keyword, url, daily_max
FROM orders AS ord
LEFT JOIN product_tasks AS tsk ON tsk.id = ord.task_id
LEFT JOIN product_groups AS grp ON grp.id = tsk.product_group
WHERE (
status = 'approved' AND
ord.total_actions_today < tsk.daily_max AND
grp.id = 1 AND
country_code = 'us'
AND last_displayed <
CASE WHEN (daily_max >= 5) THEN (NOW() - INTERVAL 30 MINUTE)
WHEN (daily_max >10) THEN (NOW() - INTERVAL 5 MINUTE)
ELSE (NOW() - INTERVAL 60 MINUTE)
END
)
GROUP BY ord.id
ORDER BY RAND()
LIMIT 3
http://sqlfiddle.com/#!2/ac4499/1
Solved DOH missing ) in the where statement
Move the last_displayed out of the CASE, such that it is compared to a single value as projected out of the CASE statement:
WHERE...
AND last_displayed <
CASE WHEN (daily_max >= 5) THEN (NOW() - INTERVAL 30 MINUTE)
WHEN (daily_max >10) THEN (NOW() - INTERVAL 5 MINUTE)
ELSE (NOW() - INTERVAL 60 MINUTE)
END;
Also note a couple of typos - INTERVAL not INTERAVAL, and just one CASE is required.
SqlFiddle here
Your structure of your WHERE was not correct. Try the following:
SELECT ord.id, keyword, url, daily_max
FROM orders AS ord
LEFT JOIN product_tasks AS tsk ON tsk.id = ord.task_id
LEFT JOIN product_groups AS grp ON grp.id = tsk.product_group
WHERE (
status = 'approved' AND
ord.total_actions_today < tsk.daily_max AND
grp.id = 1 AND
country_code = '$country' AND
(
CASE WHEN daily_max >10 THEN (NOW() - INTERAVAL 5 MINUTE)
WHEN daily_max >= 5 THEN (NOW() - INTERVAL 30 MINUTE)
ELSE (NOW() - INTERAVAL 60 MINUTE)
END > last_displayed
)
)
GROUP BY ord.id
ORDER BY RAND()
LIMIT 3
I'm using MySQL 5.0, and I need to fine tune this query. Can anyone please tell me what tuning I can do in this?
SELECT DISTINCT(alert_master_id) FROM alert_appln_header
WHERE created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
AND alert_master_id NOT IN (
SELECT DISTINCT(alert_master_id) FROM alert_details
WHERE end_date IS NULL AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
UNION
SELECT DISTINCT(alert_master_id) FROM alert_sara_header
WHERE sara_master_id IN
(SELECT alert_sara_master_id FROM alert_sara_lines
WHERE end_date IS NULL) AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
) LIMIT 5000;
The first thing that I'd do is rewrite the subqueries as joins:
SELECT h.alert_master_id
FROM alert_appln_header h
JOIN schedule_config c
ON c.schedule_name = 'Purging_Config'
LEFT JOIN alert_details d
ON d.alert_master_id = h.alert_master_id
AND d.end_date IS NULL
AND d.created_date < CURRENT_DATE - INTERVAL c.parameters DAY
LEFT JOIN (
alert_sara_header s
JOIN alert_sara_lines l
ON l.alert_sara_master_id = s.sara_master_id
)
ON s.alert_master_id = h.alert_master_id
AND s.end_date IS NULL
AND s.created_date < CURRENT_DATE - INTERVAL c.parameters DAY
WHERE h.created_date < CURRENT_DATE - INTERVAL c.parameters DAY
AND d.alert_master_id IS NULL
AND s.alert_master_id IS NULL
GROUP BY h.alert_master_id
LIMIT 5000
If it's still slow after that, re-examine your indexing strategy. I'd suggest indexes over:
alert_appln_header(alert_master_id,created_date)
schedule_config(schedule_name)
alert_details(alert_master_id,end_date,created_date)
alert_sara_header(sara_master_id,alert_master_id,end_date,created_date)
alert_sara_lines(alert_sara_master_id)
OK, this may be just a shot in the dark, but I think you don't need as many DISTINCT here.
SELECT DISTINCT(alert_master_id) FROM alert_appln_header
WHERE created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
AND alert_master_id NOT IN (
-- removed distinct here --
SELECT alert_master_id FROM alert_details
WHERE end_date IS NULL AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
UNION
-- removed distinct here --
SELECT alert_master_id FROM alert_sara_header
WHERE sara_master_id IN
(SELECT alert_sara_master_id FROM alert_sara_lines
WHERE end_date IS NULL)
AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY)
) LIMIT 5000;
Since using the DISTINCT is very costly, try to avoid it. In the first WHERE clause you are checking for ids that are NOT within some result, so it shouldn't matter if in that result some ids appear more than once.
There is a query which brings back sales data for the last 7 days.
How to get the sales of the last 30 days as well (to see the sales for the last 7 days AND the last 30 days in the results)?
SELECT
a.row_id,
MAX(ad.new_value) - MIN(ad.new_value) AS sales7days
FROM
_audit a
LEFT JOIN _audit_data ad
ON a.audit_id = ad.audit_id
WHERE ad.col = 'sales'
AND a.triggered_datetime > NOW() - INTERVAL 7 DAY
GROUP BY a.row_id
ORDER BY sales7days DESC;
Perhaps with a CASE expression:
SELECT a.row_id
, MAX(case when a.triggered_datetime > NOW() - INTERVAL 7 DAY
then ad.new_value else NULL end)
- MIN(case when a.triggered_datetime > NOW() - INTERVAL 7 DAY
then ad.new_value else NULL end) AS sales7days
, MAX(case when a.triggered_datetime > NOW() - INTERVAL 30 DAY
then ad.new_value else NULL end)
- MIN(case when a.triggered_datetime > NOW() - INTERVAL 30 DAY
then ad.new_value else NULL end) AS sales30days
FROM _audit a, _audit_data ad
WHERE a.audit_id = ad.audit_id AND ad.col = 'sales'
GROUP BY a.row_id;
SELECT
d7.row_id,
d7.salesdays, d30.salesdays
FROM
(
Select a.row_id, MAX(ad.new_value) - MIN(ad.new_value) AS salesdays
From _audit a
LEFT JOIN _audit_data ad ON a.audit_id = ad.audit_id
WHERE ad.col = 'sales' AND a.triggered_datetime > NOW() - INTERVAL 7 DAY
GROUP BY a.row_id
) d7,
(
Select a.row_id, MAX(ad.new_value) - MIN(ad.new_value) AS salesdays
From _audit a
LEFT JOIN _audit_data ad ON a.audit_id = ad.audit_id
WHERE ad.col = 'sales' AND a.triggered_datetime > NOW() - INTERVAL 30 DAY
GROUP BY a.row_id
) d30
where d7.row_id = d30.row_id
ORDER BY sales7days DESC;
assume you want the same row id for both - and either value to show, you may or may not want to make it inner or outer joined and/or COALESCE the value fields (don't know enough about the data).
I have a like the one below that does a minus from another select. The problem I have is that if the second SELECT (the one to do minus with) returns NULL, the full query returns NULL even if the first query has values. Seems like MySQL thinks 1-NULL=NULL. How can I fix this?
SELECT round(sum(iv.`amount`)) -
(
SELECT round(sum(pay.`amount`)) amountSum
FROM invoice iv
LEFT JOIN invoiceFactoring ivf on ivf.invoiceID=iv.invoiceID
LEFT JOIN user systemuser ON (systemuser.userID=iv.ownerUserID)
LEFT JOIN Payment pay ON (pay.`invoiceID`=iv.`invoiceID`)
WHERE
(iv.invoiceStateID = 2 OR iv.invoiceStateID = 3)
AND
(ivf.`invoiceFactoringProcessID` = 7)
AND (pay.`paymentMethodID` = 1 OR pay.`paymentMethodID` = 2)
AND systemuser.`groupID` = 1
AND iv.`disabled` <> 1
AND ivf.`invoiceExpiryDate` BETWEEN date_add(now(), INTERVAL - 28 DAY) AND date_add(now(), INTERVAL - 21 DAY)
)
FROM invoice iv
LEFT JOIN invoiceFactoring ivf on ivf.invoiceID=iv.invoiceID
LEFT JOIN user systemuser ON (systemuser.userID=iv.ownerUserID)
WHERE
(iv.invoiceStateID = 2 OR iv.invoiceStateID = 3)
AND
(ivf.`invoiceFactoringProcessID` = 7 or ivf.`invoiceFactoringProcessID`)
AND systemuser.`groupID` = 1
AND iv.`disabled` <> 1 /* ta bort de som är inaktiva*/
AND ivf.`invoiceExpiryDate` BETWEEN date_add(now(), INTERVAL - 28 DAY) AND date_add(now(), INTERVAL - 21 DAY)
perhaps you can wrap the "inner" sql with an IFNULL
SELECT round(sum(iv.`amount`)) -
IFNULL((
SELECT round(sum(pay.`amount`)) amountSum
FROM invoice iv
LEFT JOIN invoiceFactoring ivf on ivf.invoiceID=iv.invoiceID
LEFT JOIN user systemuser ON (systemuser.userID=iv.ownerUserID)
LEFT JOIN Payment pay ON (pay.`invoiceID`=iv.`invoiceID`)
WHERE
(iv.invoiceStateID = 2 OR iv.invoiceStateID = 3)
AND
(ivf.`invoiceFactoringProcessID` = 7)
AND (pay.`paymentMethodID` = 1 OR pay.`paymentMethodID` = 2)
AND systemuser.`groupID` = 1
AND iv.`disabled` <> 1
AND ivf.`invoiceExpiryDate` BETWEEN date_add(now(), INTERVAL - 28 DAY)
AND date_add(now(), INTERVAL - 21 DAY)
),0)
FROM invoice iv
LEFT JOIN invoiceFactoring ivf on ivf.invoiceID=iv.invoiceID
LEFT JOIN user systemuser ON (systemuser.userID=iv.ownerUserID)
WHERE
(iv.invoiceStateID = 2 OR iv.invoiceStateID = 3)
AND
(ivf.`invoiceFactoringProcessID` = 7 or ivf.`invoiceFactoringProcessID`)
AND systemuser.`groupID` = 1
AND iv.`disabled` <> 1 /* ta bort de som är inaktiva*/
AND ivf.`invoiceExpiryDate` BETWEEN date_add(now(), INTERVAL - 28 DAY) AND date_add(now(), INTERVAL - 21 DAY)
Doing anything with a null returns null. You need to define what you want to happen if it is null using COALESCE or IFNULL.
Check http://www.w3schools.com/sql/sql_isnull.asp for an example.
Seems like MySQL thinks 1-NULL=NULL.
Yes; and it is correct. "One" minus "unknown" is "unknown". If you want the second subquery's NULL to be treated as 0, then you need to wrap it in a call to the COALESCE operator: change (SELECT ...) to COALESCE((SELECT ...), 0).