I have a table exchange_rates with columns ( Id , currency, date , selling_rate).
Sample data :
Id
currency
date
selling_rate
1
usd
10/11/2021
80
2
usd
15/11/2021
82
3
usd
29/11/2021
81
4
eur
30/11/2021
95
I want to get last entered (by date) for usd selling_rate
$sql = " SELECT selling_rate
FROM echange_rates
WHERE currency=usd
ORDER BY date DESC
LIMIT 1
";
Result should be 81 (for usd latest entry is 29/11/2021)
I have tested your query using the table data you provided except I addded a couple of quotation marks for you currency column due to its string datatype. The answer I got is 81. I suppose you ran into a syntax error for that? By the way be careful with the date column you defined. By default, MySQL does not support dd/mon/year format naturally. Therefore, to adjust to your depicted data format, I used the varchar type. This is prone to mistakes when doing comparisons as the initial character value matters most. e.g. insert into tb values (5,'usd','11/12/2021',84); The answer you get is still 81 rather than 84.
My suggestion is to use the date type for the column which is meant to be a date, then use date_format function to display it in the intended way. In this case , date_format(`date`,'%d/%m/%Y') will do the work.
Related
I am parsing a json array and one field I am pulling out is closedate. However closedate has two different date formats one is YYYY-MM-DD and the other is a 13 digit timestamp. I am trying to get consistent formatting of the dates as well as have it be an integer compared to a string. Right now the query returning the close date is:
json_array_elements(ld.data->'Table1'->'Details')->>'closeDate' as closedate
and it returns close date as a string:
id
closedate
1
2021-09-29
2
1606824000000
Someone was telling me to do something like a case statement with regex. But I am not familiar with regex function. Any help is appreciated.
Edit: I have
case when x.closedate::text ~* '^[0-9]{13}$' then
to_timestamp(x.closedate::bigint/1000)
when x.closedate = '0' then null
when x.closedate = '' then null
else
to_date(x.closedate,'MMDDYYYY') end as transactionclosedate
the case statement works for converting the 13 digit timestamp to a date but I am getting the error:
ERROR: date/time field value out of range: "2020-10-23"
when trying to convert the date strings in the correct format to dates in the else part of the case statement.
An example of one way to make this work. My regex skills are not strong so others may have a better solution:
create table regex_test (id int, fld_1 varchar);
insert into regex_test values (1, '1606824000000'), (2, '2021-09-29');
select * from regex_test ;
id | fld_1
----+---------------
1 | 1606824000000
2 | 2021-09-29
select
id,
case when fld_1 ~* '^[0-9]*$' then
to_timestamp(fld_1::bigint/1000)
else
fld_1::timestamp end as ts_fld
from
regex_test;
id | ts_fld
----+------------------------
1 | 2020-12-01 04:00:00-08
2 | 2021-09-29 00:00:00-07
I hope this query help you
with data as (
select
json_array_elements(data->'Table1'->'Details')->>'closeDate' as closedate
from your_table
)
select
case when closedate::text ~ '^[0-9]+$' then
to_timestamp(closedate::numeric / 1000)::date
else
closedate::date
end
from data;
Either of the other answers would be ok providing that only the specified formats exist. However, containing those formats requires a text field; which may contain anything. It is dangerous to assume if the content is not 13 digits then it is a valid formatted ISO date. I would validate that as well (and verify digits length).
select id,
, case when closedate ~* '^[0-9]{13}$' then
to_timestamp(closedate::bigint/1000)
when is_valid_iso_date(closedate) then
closedate::timestamp
else
'-infinity'::timestamp -- or whatever to indicate Invalid Date.
from <your table> ;
The problem being that is_valid_iso_date function. It turns out however I had to create just that a couple years ago, I'll make the result available here.
DISCLAIMER: While the function has given no known erroneous results it has NOT been exhaustively tested.
i have a table like this
|id| date |name|
1 23/11/20 jake
2 01/07/20 jhon
3 23/05/20 blake
4 11/02/20 drake
5 1/03/14 crake
i ran a query like this
WHERE date >= '1/07/20' AND date <= '23/11/20'
i expected a result where i would get only the results between those dates
but i got some results which were from 2014
the data type for the date column is varchar
#note i can not change the datatype
how can i only get dates between the two ?
String-wise comparison is the problem: typically, '10/01/19' (Janurary 10th, 2019) is greater than '01/01/20' (January 1st, 2020), because the former starts with 1, and the later with 0.
You need to turn these strings to dates before you can compare them:
where str_to_date(date, '%d/%m/%y') between '2020-07-01' and '2020-66-23'
This is inefficient, because the entire column needs to be converted before the filtering can happen. I would warmly recommend fixing your data model, and store dates as dates.
Side note: your strings need to be consistently formatted as mm/dd/yy for this to work; if you have varying formats - or strings that do not map to valid dates - then you have a bigger problem than what you have asked here.
SELECT * FROM table WHERE '2016-03-31' > (SELECT MAX(year) from table where bill_id = 'somevalue')
I am using above query to check if 2016-03-31 is greater than all years present in table against bill_id. It is working fine. but is it correct approach to compare dates. dates will always in above format. Is there any need to convert date format for comparison. value 2016-03-31 will change dynamically but it will be always in Y-m-d format
Note : year is column name which contains full date in Y-m-d format like 2016-05-20
You are not comparing dates. You are comparing a string '2016-03-31' with a number, e.g. 2015.
In order to compare, MySQL silently converts the string to number. One would expect this to crash, as '2016-03-31' certainly isn't a number. MySQL, however, reads from left to right and takes from there all that can be considered a number, i.e. '2016'. Well, one could argue that some people put a minus sign at the end of a number, so this should be '2016-', i.e. -2016. Anyway, MySQL stops before the minus sign, gets 2016 and uses this for the comparision.
I don't know if all this is guaranteed to work in the future. I would not rely on this.
What result would you expect anyway? Is the 31st of March 2016 greater than the year 2016? That's a queer question, don't you think?
Try this. But do you really have a column year that stores only year?
SELECT * FROM table WHERE year(STR_TO_DATE('2016-03-31'))
> (SELECT MAX(year) from table where bill_id = 'somevalue')
SELECT * FROM table WHERE YEAR('2016-03-31') > (SELECT MAX(year) from table where bill_id = 'somevalue')
MySQL YEAR() returns the year for a given date or timestamp. The return value is in the range of 1000 to 9999 or 0 for 'zero' date.
I have a mySQL query which is outputting decimal fields with a comma.
SELECT Metals.Metal, FORMAT(Fixes.GBPam, 3) AS AM, FORMAT(Fixes.GBPpm, 3) AS PM,
DATE_FORMAT(Fixes.DateTime, '%d-%m-%y') AS Date
FROM Fixes, Metals
WHERE Metals.Id = Fixes.Metals_Id
Fields GBPam and GBPpm are both of type decimal(10,5)
Now I want columns AM and PM to be formatted to 3 decimal places in my sql query - Correct
I want values in the thousands to be formatted as xxxx.xxx and not x,xxx.xxx - Incorrect
Example output from mysql query:
Metal AM PM Date
Gold 1,081.334 NULL 11-09-12
Silver 21.009 NULL 10-09-12
Platinum 995.650 NULL 11-09-12
Palladium 416.700 NULL 11-09-12
Can you see that output for Gold AM is 1,081.334? How can I get it to output 1081.334?
This is a pain in the ass for me because I have to then muck about in PHP to remove the comma. I would prefer to just get mysql to format it correctly.
Just use ROUND, this is a numeric function. FORMAT is a string function
ROUND(Fixes.GBPam, 3)
you can use replace command for this purpose.
REPLACE(Fixes.GBPam,',','')
EDIT:
With respect to your question you could do something like this:
SELECT Metals.Metal, ROUND(REPLACE(Fixes.GBPam,',',''),3) AS AM,
ROUND(REPLACE(Fixes.GBPpm,',',''),3) AS PM,
DATE_FORMAT(Fixes.DateTime, '%d-%m-%y') AS Date
FROM Fixes, Metals
WHERE Metals.Id = Fixes.Metals_Id
Use replace function. Whether the field is integer or varchar, it will work.
select replace(Fixes.GBPam,',','.');
Using Access 2003
Table
ENO Time
001 020000
001 040000
001 220000
002 030000
002 050000
005 230000
So on…,
Time Date type is Varchar in the Database. How to convert a Varchar into Datetime?
Here I want to get a total of time for the ENO.
Select eno, sum (time) from table group by eno
It showing error like – data type mismatch criteria error
Expected Output
001 26:00:00
002 08:00:00
So on…,
Need Query Help.
You are best off working in seconds. Use the Mid() function to break up the string and calculate the number of seconds, sum the times, and then format the result however you like. If you write it as a single query you'll need to use the same long expression in three different places, so for improved readability I would do it as two queries. The first is:
SELECT eno, sum(val(mid(time,1,2))*3600+val(mid(time,3,2))*60+val(mid(time,5,2))) AS secs
FROM table
GROUP BY eno;
Save this query in access as "enosums", for example. The second query is:
SELECT eno, format(secs/3600, "00:") & format((secs/60 Mod 60), "00:") & format(secs Mod 60, "00")
FROM enosums;
The reason I suggest this method is that even if you manage to convert to datetime values (which you can do by using the Mid() function and concatenation operator to convert the "hhmmss" string into "hh:mm:ss" format and then apply the TimeValue function), there is no easy way to print this in the output format you need because the Format() function will only go up to 23:59:59 and then wrap back to 00:00:00.