What's wrong with this mySQL query? (concat and cast) - mysql

The following mySQL query always returns 0 results. The problem began when I added the part that uses the concat and the cast functions. Can you see any syntax error in it?
SELECT p.seccio_id as seccio,
count(distinct r.usuari_upc) as usuaris,
sum(r.preu) as preu
FROM report r, persona p
WHERE r.usuari_upc = p.persona_id
and ((r.any = 2017 and r.mes = 1)
or (r.any > 2017 and r.any < 2018)
or (r.any = 2018 and r.mes = 1)
or (2017 != 2018
and ((r.any = 2017 and r.mes > 1)
or (r.any = 2018 and r.mes < 1))))
and (p.any_id = '2017-2018'
or p.any_id = '2016-2017')
/* The problem is here. */
and ((r.mes < 9
and p.any_id = CONCAT(CAST(r.any - 1 as varchar(4)),"-",CAST(r.any as varchar(4))))
or (r.mes >= 9 and p.any_id = CONCAT(CAST(r.any as varchar(4)),"-",CAST(r.any + 1 as varchar(4)))))
GROUP BY p.seccio_id
ORDER BY p.seccio_id

You can't cast straight from the numeric values to varchar(4) - if you change them all to char(4), you lose the syntax errors.

Related

SSRS SWITCH showing error rather than answer

I am trying to do a simple calculation for my data. When the Order value = 6, then subtract the values of order = 1 - 2 -3. It returns #error instead of the the answer. How can i make it work correctly?
= SWITCH(
Fields!Order.Value = 6,
Sum(IIF( Fields!Order.Value = 1 ,CDBL(Fields!Totals.Value),CDBL(0)))
- Sum(IIF( Fields!Ordering.Value = 2 ,CDBL(Fields!Totals.Value),CDBL(0)))
- Sum(IIF( Fields!Ordering.Value = 3 ,CDBL(Fields!Totals.Value),CDBL(0)))
,
1 = 1,Sum(Fields!Totals.Value)
)

How to convert datetime.datetime to datetime.date?

From my sql query I'm getting output as datetime.datetime(2020, 9, 22, 0, 0)
query = '''SELECT checkin_date FROM `table1`
WHERE checkin_date BETWEEN %s AND %s'''
cursor.execute(query,(startDate, endDate)
results = cursor.fetchall()
#results:
#[(datetime.datetime(2020, 9, 22, 0, 0), datetime.datetime(2020, 9, 24, 0, 0))]
for res in results:
## When I print type I get correct result
print(type(res[0]) ## <type 'datetime.datetime'>
##when I compare with another datetime.date (currentDate variable)
if res[0] < currentDate:
## I get error `TypeError: can't compare datetime.datetime to datetime.date` *which is expected*
## But when I use .date()
if res[0].date() < currentDate:
## I get `TypeError: can't compare datetime.date to unicode`
I tried converting currentDate to datetime.datetime, but still doesn't work. Can't seem to figure out what's the issue here.
To force your query to spit out the date format you want, change it to this:
SELECT DATE_FORMAT(checkin_date, '%Y-%c-%d')
FROM table1
WHERE DATE(checkin_date) BETWEEN %s AND %s
To make it able to use an index on your checkin_date column, change it to this.
SELECT DATE_FORMAT(checkin_date, '%Y-%c-%d')
FROM table1
WHERE checkin_date >= DATE(%s)
AND checkin_date < DATE(%s) + INTERVAL 1 DAY
Try this
splitting a datetime column into year, month and week
SELECT Year(checkin_date), Month(Checkin_date), Day(Checkin_date),
FORMAT(GETDATE(),'HH'), FORMAT(GETDATE(),'mm')
FROM table1
WHERE (CAST(checkin_date AS DATE) BETWEEN '2018-01-01' AND '2020-01-01')
Note: Use 'HH' for 24 hours format and 'hh' for 12.

MySQL Convert From Seconds To Another Custom Format

I have this javascript code that works fine:
function timeup(s) {
var d, h, m, s;
m = Math.floor(s / 60);
s = s % 60;
h = Math.floor(m / 60);
m = m % 60;
d = Math.floor(h / 24);
h = h % 24;
m = m > 9 ? m : "0"+m;
h = h > 9 ? h : "0"+h;
s = s > 9 ? s : "0"+s;
if (d > 0) {
d = d+" days ";
} else {
d = "";
}
return d+h+":"+m+":"+s;
}
SO i need same function but in MySQL(because i do SQL query and don't want to use javascript conversion on client side)
So i need to convert in MySQL seconds to get this same output:
timeup(600000) => 6 days 22:40:00
timeup(60000) => 16:40:00
timeup(6000) => 01:40:00
timeup(600) => 00:10:00
timeup(60) => 00:01:00
timeup(60) => 00:01:00
timeup(6) => 00:00:06
So if seconds below day show HH:MM:SS if seconds greater that day show X days HH:MM:SS
I im trying using CONCAT & TIMESTAMPDIFF but i think maybe it should go if then to compare day below 24h or grater to show custom string X days...any help welcome.
I tested this and it seems to do the job:
DROP FUNCTION IF EXISTS GET_HOUR_MINUTES;
DELIMITER $$
CREATE FUNCTION GET_HOUR_MINUTES(seconds INT)
RETURNS VARCHAR(16)
BEGIN
RETURN CONCAT(LPAD(FLOOR(HOUR(SEC_TO_TIME(seconds)) / 24), 2, 0), ' days ',TIME_FORMAT(SEC_TO_TIME(seconds % (24 * 3600)), '%H:%i:%s'));
END;
$$
DELIMITER ;
Test it like this:
SELECT GET_HOUR_MINUTES(600001);
That returns
'06 days 22:40:01'
It seems to want, at least in MySQL Workbench, to have the database you are using selected before you run it. It saves the function within the database, that is, you can see it in the column on the left with Tables, Views, Stored Procedures and Functions.
I now have another problem with this above function that works only on seconds..but i forget to ask in first question that i have in database stored number:
uptime => 1507977507423
And i need to get seconds and show above format from NOW() time
So for example if i have uptime in database so formula will be: NOW() - uptime, i try using this but i get strange output like 34 days 838:59:59 and that is not correct:
SELECT
CONCAT(LPAD(FLOOR(HOUR(SEC_TO_TIME(UNIX_TIMESTAMP(NOW())-SUBSTRING(uptime, 1, length(uptime) - 2))) / 24), 2, 0), ' days ',TIME_FORMAT(SEC_TO_TIME(UNIX_TIMESTAMP(NOW())-SUBSTRING(uptime, 1, length(uptime) - 2) % (24 * 3600)), '%H:%i:%s')) AS nice_date
FROM streams
WHERE id=1;
I get this:
+-------------------+
| nice_date |
+-------------------+
| 34 days 838:59:59 |
+-------------------+

Mysql to Informix query

I used following query to retrieve information from a mysql table.
SELECT YEARWEEK(fecha,2) ,CONCAT('Semana ', WEEK(fecha)) as y,count(*) as a
FROM mobile09
WHERE fecha BETWEEN TODAY - 30 AND TODAY GROUP BY 1 ORDER BY 1 ASC
How can I get the same result in a Informix database with same tables?
You're going to have to implement your own week of year function for Informix.
Lucky for you, this has already been done at: IBM Developerworks
CREATE FUNCTION day_one_week_one(yyyy INTEGER)
RETURNING DATE
WITH(NOT VARIANT)
DEFINE jan1 DATE;
LET jan1 = MDY(1, 1, yyyy);
RETURN jan1 + MOD(11 - WEEKDAY(jan1), 7) - 3;
END FUNCTION;
CREATE FUNCTION iso8601_weeknum(dateval DATE DEFAULT TODAY)
RETURNING CHAR(2)
WITH(NOT VARIANT)
DEFINE rv CHAR(8);
DEFINE yyyy CHAR(4);
DEFINE ww CHAR(2);
DEFINE d1w1 DATE;
DEFINE tv DATE;
DEFINE wn INTEGER;
DEFINE yn INTEGER;
-- Calculate year and week number.
LET yn = YEAR(dateval);
LET d1w1 = day_one_week_one(yn);
IF dateval < d1w1 THEN
-- Date is in early January and is in last week of prior year
LET yn = yn - 1;
LET d1w1 = day_one_week_one(yn);
ELSE
LET tv = day_one_week_one(yn + 1);
IF dateval >= tv THEN
-- Date is in late December and is in the first week of next year
LET yn = yn + 1;
LET d1w1 = tv;
END IF;
END IF;
LET wn = TRUNC((dateval - d1w1) / 7) + 1;
-- Calculation complete: yn is year number and wn is week number.
-- Format result.
LET yyyy = yn;
IF wn < 10 THEN
LET ww = "0" || wn;
ELSE
LET ww = wn;
END IF
RETURN ww;
END FUNCTION;
Now you should be able to do
select
year(fecha) || iso8601_weeknum(fecha),
'Semana ' || iso8601_weeknum(fecha) as y,
count(*) as a
from
mobile09
where
fecha between today - 30 and today
group by
1, 2
order by
1 asc;

Add 28 to last 2 digit of date and replace the order

I have a number such as this : 840106
I need to do the following :
Change the number to date add - and flip the number : 06-01-84
add 28 to the last 2 digit that the date will be : 06-01-12
84 + 16 = 00 + 12 = 12
number is always changing sometimes it cab be 850617 , but format is always same add - and add 28 last 2 digit.
any ideas how to help me here ?
Here is a sqlite solution:
create table t( c text);
insert into t (c) values(990831);
insert into t (c) values(840106);
insert into t (c) values(800315);
insert into t (c) values(750527);
insert into t (c) values(700923);
insert into t (c) values(620308);
select c, substr(c,5,2) || '-' || substr(c,3,2) || '-' ||
case when (substr(c,1,2) + 28) < 100 then (substr(c,1,2) + 28)
else case when ((substr(c,1,2) + 28) - 100) < 10 then '0' || ((substr(c,1,2) + 28) - 100)
else ((substr(c,1,2) + 28) - 100)
end
end
from t;
For formatting you can use
http://www.w3schools.com/sql/func_date_format.asp
For adding days to the date you should take a look at date_add() function
mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
Assuming date is the name of the column containing your date:
DATE_FORMAT(DATE_ADD(STR_TO_DATE(date, %y%m%d), INTERVAL 28 YEAR), %d-%m-%y);
What this does is first formats the string into a date, then adds 28 years, then converts back to string with the new format.
SQLite is a lot tricker with this, you'll need to use substrings.
substr(date,5) || "-" || substr(date,3,4) || "-" || CAST(CAST(substr(date,1,2) as integer) + 28 - 100) as text
I'm not too experienced with SQLite so the casting may be a bit weird.
Here is a t-sql solution that you can use and migrate to mysql.
declare #myDate as char(8) = '840106';
declare #y as char(2), #m as char(2), #d as char(2);
set #y = LEFT (#myDate, 2);
declare #yi as int = Convert (int, #y);
IF #y between 30 and 99 ----------- pick a cut-off year
SET #yi = (28 - (100-#yi));
SET #y = CONVERT(char, #yi)
set #m = SUBSTRING(#myDate, 3, 2);
set #d = SUBSTRING(#myDate, 5, 2);
SET #myDate = #d + '-' + #m + '-' + #y;
PRINT #myDate;