MySQL does not convert string to int, despite casting it - mysql

So what I am trying to do is to substract number of week from date, easy, right?
However, query returns a string I believe, because no matter how I try to sort it, it still gets sorted in that order: 0, 1, 10, 11, 12, ... 19, 2, 21
Of course I have googled, I have already tried CAST AS SIGNED/UNSIGNED/INT/DECIMAL. I did try to FORMAT it, multiply by one, add zero to result - nothing happens.
I use my query in BIRT - as I have managed to get it sorted in BIRT table, it still gets scrumbled in Workbench and BIRT charts - and it makes them look like nonsense.
Now as I write this post I see that the problem is that I have CASE there:
SELECT CASE WHEN 2 = 1 THEN SUBSTR(mydate, 1, 7) ELSE CAST(WEEK(mydate, 0) AS SIGNED) END AS 'data' FROM mytable
Still: why does CAST not work when it's accompanied with CASE that might return a string? I wanted to conditionally let users choose whether the data is grouped by YYYY-MM (year and month) OR by weeks, now it seems I got kind of stuck.

That casting (CAST(WEEK(mydate, 0) AS SIGNED)) looks unnecessary to me since week() function returns week number in INT. So probably you can cast the result of week() to varchar since substring will result in varchar
CASE WHEN 2 = 1 THEN SUBSTR(mydate, 1, 7) ELSE CAST(WEEK(mydate, 0) AS CHAR(100)) END AS data
FROM mytable

Related

MySQL STR_TO_DATE Problem while using this function

As title, I'm trying to convert a VARCHAR column in a DATE column, and data is populated in that format "DDMMYYYY" ex. XMAS is "25122022" and in this case the correct formula should be STR_TO_DATE(column, '%d%m%Y')Well, when I execute this query I get an error since in some cases I have values with a "missing" char, I mean, for example, "1012023" when the day is <10 the query fails, cause it checks for "01122023" instead.I could solve this easily by adding a 0 to all fields having length 7, but I'd like to make it more clean.Reading better the usage of STR_TO_DATE I noticed that I could replace %d with %e since the second choice should theorically consider days from 0 to 31 instead of 01 to 31.Unexpectedly the query didn't work and gave me the same erorr at the first instance of a length 7 string.Am I doing something wrong?Thanks in advance.
We can try left padding your date string with zero to a length of 8:
WITH yourTable AS (
SELECT '1012023' AS dt
)
SELECT STR_TO_DATE(LPAD(dt, 8, '0'), '%d%m%Y') AS dt_out -- 2023-01-01
FROM yourTable;
Demo

MYSQL case statment comparing string values incorrect outcome

I have the following mysql query with what should be a simple case statement in comparing two srting values and populating whichever is the greater value as follows:
SELECT
wca.bond.secid,
wca.bond.IssueAmount,
wca.bochg.NewOutValue,
case when wca.bond.IssueAmount >= wca.bochg.NewOutValue
then wca.bond.IssueAmount ELSE wca.bochg.NewOutValue END AS IssueAmount2
from
wca.bond
INNER JOIN wca.bochg ON wca.bond.secid = wca.bochg.SecID
WHERE
bond.secid = 5955156;
The following output is produced:
As you can see from the output the case statment does snot seem to work as it should as I would expect to see 12200 as the value under IssueAmount2 as opposed to 7200. I thought it may be due to the fields being compared being different formats but I can confirm they are both Varchars having the same length 20.
Does anyone know why I'm having this issue?
In VARCHAR() datatype, it will compare the first character. If the first character is the same, it will compare the second character and continue the comparison until it found a difference. In your case, although it's obvious that 12200 is more than 7200, that's only true if we're comparing numbers. So, with varchar, this is what happen:
[7]200 = 7 is bigger than 1
[1]2200 = 1 is smaller than 7
So what you need is to convert the value into integer. Here's a suggestion to your current query:
SELECT
wca.bond.secid,
wca.bond.IssueAmount,
wca.bochg.NewOutValue,
case when wca.bond.IssueAmount+0 >= wca.bochg.NewOutValue+0
then wca.bond.IssueAmount ELSE wca.bochg.NewOutValue END AS IssueAmount2
from
wca.bond
INNER JOIN wca.bochg ON wca.bond.secid = wca.bochg.SecID
WHERE
bond.secid = 5955156;
Add +0 to the column in comparison to quickly make the column value identified as integer. You can also use CONVERT() or CAST():
CONVERT(varchar_val1, SIGNED) >= CONVERT(varchar_val2, SIGNED)
...
or
CAST(varchar_val1 AS SIGNED) >= CAST(varchar_val2 AS SIGNED)
...
Demo fiddle

Casting negative integer to DATE in SQL

I'm having a problem working with a Navicat Database. I got a column in SQL called fechaNacimiento (Birthdate) that should be a Date type, but instead it's stored as integers (most negative integers):
SELECT fechaNacimiento FROM Registrados
And I'm getting:
fechaNacimiento
-1451678400
-2082829392
-1798746192
-1199221200
-1356984000
-694299600
-1483214400
-1924976592
-1830368592
-2019670992
-1678909392
239252400
1451617200
-879541200
I don't know how this dates where loaded, I just know that inside that negative integer there's a date, and nobody here have any clue about how to spell SQL, so I have nobodoy to ask. If I just cast it to DATETIME, I get all of them as NULL values. Any idea in how to convert this data to Date type?
Numbers like that make me think of Unix times, number of seconds since 1970. If so, you might be able to do:
select dateadd(second, <column>, '1970-01-01')
This would put the negative values sometime before 1970 (for instance, -1678909392 is 1916-10-19). If you have older dates, then that might be the format being used.
These might also be represented as milliseconds. If so:
select dateadd(second, <column>/1000, '1970-01-01')
In this case, -1678909392 represents 1969-12-12.
In MySQL, you would use:
select '1970-01-01' + interval floor(column / 1000) second

SQL query to select values grouped by hour(col) and weekday(row) based on the timestamp

I have searched SO for this question and found slightly similar posts but was unable to adapt to my needs.
I have a database with server requests since forever, each one with a timestamp and i'm trying to come up with a query that allows me to create a heatmatrix chart (CCC HeatGrid).
The sql query result must represent the server load grouped by each hour of each weekday.
Like this: Example table
I just need the SQL query, i know how to create the chart.
Thank you,
Those looks like "counts" of rows.
One of the issues is "sparse" data, we can address that later.
To get the day of the week ('Sunday','Monday',etc.) returned, you can use the DATE_FORMAT function. To get those ordered, we need to include an integer value 0 through 6, or 1 through 7. We can use an ORDER BY clause on that expression to get the rows returned in the order we want.
To get the "hour" across the top, we can use expressions in the SELECT list that conditionally increments the count.
Assuming your timestamp column is named ts, and assuming you want to pull all rows from the year 2014, we start with something like this:
SELECT DAYOFWEEK(t.ts)
, DATE_FORMAT(t.ts,'%W')
FROM mytable t
WHERE t.ts >= '2014-01-01'
AND t.ts < '2015-01-01'
GROUP BY DAYOFWEEK(t.ts)
ORDER BY DAYOFWEEK(t.ts)
(I need to check the MySQL documentation, WEEKDAY and DAYOFWEEK are real similar, but we want the one that returns lowest value for Sunday, and highest value for Saturday... i think we want DAYOFWEEK, easy enough to fix later)
The "trick" now is the columns across the top.
We can extract the "hour" from timestamp using the DATE_FORMAT() function, the HOUR() function, or an EXTRACT() function... take your pick.
The expressions we want are going to return a 1 if the timestamp is in the specified hour, and a zero otherwise. Then, we can use a SUM() aggregate to count up the 1. A boolean expression returns a value of 1 for TRUE and 0 for FALSE.
, SUM( HOUR(t.ts)=0 ) AS `h0`
, SUM( HOUR(t.ts)=1 ) AS `h1`
, SUM( HOUR(t.ts)=2 ) AS `h2`
, '...'
, SUM( HOUR(t.ts)=22 ) AS `h22`
, SUM( HOUR(t.ts)=23 ) AS `h23`
A boolean expression can also evaluate to NULL, but since we have a predicate (i.e. condition in the WHERE clause) that ensures us that ts can't be NULL, that won't be an issue.
The other issue we can encounter (as I mentioned earlier) is "sparse" data. To illustrate that, consider what happens (with our query) if there are no rows that have a ts value for a Monday. What happens is that we don't get a row in the resultset for Monday. If it does happen that a row is "missing" for Monday (or any day of the week), we do know that all of the hourly counts across the "missing" Monday row would all be zero.

SQL Server DateTime cast from VarChar

I've got a table with 9 million records. Each one has a "BirthDate" field that is stored as a varchar. I'm trying to select all where the birthdate is 25 years or less (all people 25 or under). It's failing, because somewhere in this monstrosity of a table, there is an invalid value.
select COUNT(*) from LeadSplit where CAST(LeadSplit.Birthdate as datetime) > DATEADD(yy, -26, getdate()) and Birthdate is not null
The error is:
Msg 242, Level 16, State 3, Line 1
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
I'm at a loss as to how to find the row with the invalid value, and also, how to deal with it. I would like to just ignore it or fix it.
You could try to find the offending rows by doing something like:
SELECT (some ID), Birthdate
FROM dbo.YourTable
WHERE ISDATE(Birthdate) = 0
This might not work for all cases - but it might give you a starting point.
The error you are getting is that one or more of the dates cannot be parsed given the DateFormat setting.
Set DateFormat MDY
GO
Select Count(*)
From LeadSplit
Where Case
When IsDate(BirthDate) = 0 Then 0
When BirthDate >= DateAdd(yyyy,-25,CURRENT_TIMESTAMP) Then 1
End = 1
Try to use CONVERT instead of CAST and explicit specify date format. MSDN Article about CAST and CONVERT