I have three dates data_a,date_b & date_main. All of them TIMESTAMP that outputs values likes this 2018-06-20 11:11:20.
Sometimes date_a or date_b are NULL, date_main is always present (NOT NULL).
Why when trying to compare them using GREATEST(), it outputs blanks (NULL) values ""?
GREATEST(MAX(l.date_a),MAX(r.date_b),p.date_main) AS date,
You could use COALESCE to handle NULL values for every column that is nullable:
GREATEST(COALESCE(MAX(l.date_a), '1900-01-01'),
COALESCE(MAX(r.date_b), '1900-01-01'),
p.date_main
)AS date
As you want greatest value I would exchange NULL with some date from the past(arbitrary value).
If p.date_main is never NULL, I would use:
GREATEST(COALESCE(MAX(l.date_a), p.date_main),
COALESCE(MAX(r.date_b), p.date_main),
p.date_main
) AS date,
GREATEST() and LEAST() (unlike MIN() and MAX()) return NULL if any of the arguments are NULL. So, if all the values in a group are NULL, then MIN() and MAX() return NULL. The COALESCE() replaces the value with p.date_main for the comparison for the greatest value.
Related
I have a table where user input a target date, and then I want to output the count of names where their associated target date is greater than current date.
I tried but I'm getting the same results
below is the code
$select1_query = "
SELECT ACCOUNT_NAME
, COUNT(NCI_NUMBER)
, COUNT(CURDATE()>TARGET_DATE)
FROM sim_tracker
WHERE NCI_STATUS != 'Closed'
GROUP
BY ACCOUNT_NAME
";
Don't use count(). Use sum():
SELECT ACCOUNT_NAME,
COUNT(NCI_NUMBER),
SUM(CURDATE() > TARGET_DATE)
FROM sim_tracker
WHERE NCI_STATUS <> 'Closed'
GROUP BY ACCOUNT_NAME;
This works because MySQL treats booleans expressions as "1" for true and "0" for false in a numeric context. SUM() then counts the number of "true" values.
COUNT() does not work, because COUNT(<expression>) counts the number of non-NULL values. "true" and "false" are both non-NULL, so they both get counted.
I have a table with a Date column. It has a row where my_date column's value is 2017-11-24
SELECT * FROM mytable WHERE my_date = '2017-11-24 00:00:00' returns that row.
While SELECT * FROM mytable WHERE my_date = '2017-11-24 00:00:01' does not.
From mysql doc; this page says
If one of the arguments is a TIMESTAMP or DATETIME column and the
other argument is a constant, the constant is converted to a timestamp
before the comparison is performed. This is done to be more
ODBC-friendly. This is not done for the arguments to IN().
If I am interpreting this correctly, in the second query, the constant on right side would be implicitly casted to Date field
The second page for casting says -
Conversion to a DATE value takes fractional seconds into account and
rounds the time part. For example, '1999-12-31 23:59:59.499' becomes
'1999-12-31', whereas '1999-12-31 23:59:59.500' becomes '2000-01-01'.
The example shows 1999-12-31 23:59:59.499 -> 1999-12-31. I understand explicit casting is preferred, but I am wondering why mysql chose to typecast the column value instead of constant or if there's something else happening here.
I don't think you are interpreting the docs correctly. The first page you quote is about comparing a DATETIME or TIMESTAMP to a constant. You are comparing a DATE to a constant, so this logic should apply:
Conversion of DATE values:
Conversion to a DATETIME or TIMESTAMP value adds a time part of '00:00:00' because the DATE value contains no time information.
So it's like comparing '2017-11-24 00:00:00' = '2017-11-24 00:00:01' which sensibly returns false.
Comparing DATEs to DATETIMEs/TIMESTAMPs is similar to comparing an int to a double in that the implicit conversion applies to the less precise value. You would not expect 42 to match 42.1, and likewise you shouldn't expect 2017-11-24 to match 2017-11-24 00:00:01.
I have two related table,a one to many relations.I can display values on a selected column in where condition
What is the correct way when adding 'AND' clause in the above query?I tried this queries but it result empty set.
The values in date_created all include a time component 08:00:00. However, you are comparing it as equal to the date value '2014-03-13' which implies 2014-03-12 00:00:00, and is therefore not equal to 2014-03-12 08:00:00
To make that comparison the way you are attempting, you need to truncate the value in date_created to only the date portion, removing the time with MySQL's native DATE() function.
SELECT date_created
FROM collections
WHERE
-- Truncate the datetime to a date only
DATE(date_created) = '2014-03-12'
AND loan_id = 3942
The above example is that of your first query attempt, but using the JOIN requires the same solution in the WHERE clause.
I found a solution to my problem. I change my query into
SELECT
date_created
FROM collections
WHERE DATE(date_created) = '2014-03-12' AND loan_id = 3942;
Now it returns rows with the specific dates.
Clearly, I am missing the forest for the trees...I am missing something obvious here!
Scenario:
I've a typical table asset_locator with multiple fields:
id, int(11) PRIMARY
logref, int(11)
unitno, int(11)
tunits, int(11)
operator, varchar(24)
lineid, varchar(24)
uniqueid, varchar(64)
timestamp, timestamp
My current challenge is to SELECT records from this table based on a date range. More specifically, a date range using the MAX(timestamp) field.
So...when selecting I need to start with the latest timestamp value and go back 3 days.
EX: I select all records WHERE the lineid = 'xyz' and going back 3 days from the latest timestamp. Below is an actual example (of the dozens) I've been trying to run.
MySQL returns a single row with all NULL values for the following:
SELECT id, logref, unitno, tunits, operator, lineid,
uniqueid, timestamp, MAX( timestamp ) AS maxdate
FROM asset_locator
WHERE 'maxdate' < DATE_ADD('maxdate',INTERVAL -3 DAY)
ORDER BY uniqueid DESC
There MUST be something obvious I am missing. If anyone has any ideas, please share.
Many thanks!
MAX() is an aggregated function, which means your SELECT will always return one row containing the maximum value. Unless you use GROUP BY, but it looks that's not what you need.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_max
If you need all the entries between MAX(timestamp) and 3 days before, then you need to do a subselect to obtain the max date, and after that use it in the search condition. Like this:
SELECT id, logref, unitno, tunits, operator, lineid, uniqueid, timestamp
FROM asset_locator
WHERE timestamp >= DATE_ADD( (SELECT MAX(timestamp) FROM asset_locator), INTERVAL -3 DAY)
It will still run efficiently as long as you have an index defined on timestamp column.
Note: In your example
WHERE 'maxdate' < DATE_ADD('maxdate',INTERVAL -3 DAY)
Here you were are actually using the string "maxdate" because of the quotes causing the condition to return false. That's why you were seeing NULL for all fields.
Edit: Oops, forgot the "FROM asset_locator" in query. It got lost at some point when writing the answer :)
I'm trying to get the date difference between two columns and then ultimately, get the average days grouped by the contractor field. I was able to get most of the SQL down but I can't seem to figure out how to get the date difference for multiple if scenarios.
Basically, if the original date column is null and the new date column is not, get the date difference between the new date and date ordered. Vice versa. If both original and new date are null, just set the date diff to null. It should look like below, without accounting for the grouped average days.
SQL below (didn't include avg function yet):
SELECT PT1.CONTRACTOR AS 'Contractor', PT1.date_order AS "date ordered", PT1.DATE_COMPLETED AS "original date", PT2.DATE_COMPLETED AS "new date",
IF(PT1.DATE_COMPLETED = NULL AND PT2.DATE_COMPLETED IS NOT NULL, DATEDIFF(PT2.DATE_COMPLETED, PT1.DATE_ORDER), IF(PT2.DATE_COMPLETED = NULL AND PT1.DATE_COMPLETED IS NOT NULL, DATEDIFF(PT1.DATE_COMPLETED, PT1.DATE_ORDER), NULL)) AS "DATE DIFF"
FROM PTABLE1 PT1
INNER JOIN PTABLE2 PT2
ON PT1.ID = PT2.ID
WHERE PT2.STATUS = 'To_do' OR PT2.STATUS = 'Completed'
AND PT2.COMPLETE = 'Yes'
-- GROUP BY PT1.CONTRACTOR
COALESCE is your friend - it returns the first non-null value in a list, or NULL if they are all NULL.
So what you want is probably
datediff(coalesce(original_date, new_date), order_date)
If both are null, datediff will return null.