MySQL Calculations using variables - mysql

Why is this not working? I would like to get the result of:
(#sum_hours * #rate_hours) + (#sum_travel * #rate_travel) + (#sum_miles * #rate_miles)
The results of my sub queries are as follows:
#sum_hours = 5.00000, #sum_travel = 2.00000, #sum_miles = 0.00000
#rate_hours = 35.00000, #rate_travel = 35.00000, #rate_miles = NULL
#_rate_hours = CAST(IF(#rate_hours, #rate_hours, 0) AS DECIMAL(10, 5)) = 35.00000
#_rate_travel = CAST(IF(#rate_travel, #rate_travel, 0) AS DECIMAL(10, 5)) = 35.00000
#_rate_miles = CAST(IF(#rate_miles, #rate_miles, 0) AS DECIMAL(10, 5)) = 0.00000
So now that I have some values, I'm doing:
#total:= (#sum_hours * #_rate_hours)
I expect this to be 175, but it returns NULL. If I directly declare #sum_hours as 5
#sum_hours:= 5
I get 175, as expected. Am I doing something wrong? How can I get this to return 175, assuming I don't know that the values are supposed to be 5, 35 and 175?
#sum_hours is being cast as decimal, but with and without the cast it does not work.
Edit:
This is a stripped back version of the query, as the JOINs and subqueries aren't relevant, just the return details. All numeric fields are stored as FLOAT in the database. The values are confirmed in the result, but the calculation for #total does not work (returns null).
I have worked around this using COALESCE and some other bits, but I'm still curious as to why it would not calculate properly - or what I'm doing wrong.
SELECT
#sum_hours:= CAST(hours AS DECIMAL(10, 5)),
#sum_travel:= CAST(travel AS DECIMAL(10, 5)),
#sum_miles:= CAST(miles AS DECIMAL(10, 5)),
#rate_hours:= (SELECT ... returns 35),
#rate_travel:= (SELECT ... returns 35),
#rate_miles:= (SELECT ... returns NULL),
#_rate_hours = CAST(IF(#rate_hours, #rate_hours, 0) AS DECIMAL(10, 5)),
#_rate_travel = CAST(IF(#rate_travel, #rate_travel, 0) AS DECIMAL(10, 5)),
#_rate_miles = CAST(IF(#rate_miles, #rate_miles, 0) AS DECIMAL(10, 5)),
#total:= (#sum_hours * #_rate_hours) + (#sum_travel * #_rate_travel) + (#sum_miles * #_rate_miles)
FROM table
WHERE
id = '...'
GROUP BY id

Related

How to auto increment a string with sql query

I am stuck at a point where i have to increment a string, and my strings are of type C001,SC001,B001
in my data base they are defined like
what i am trying to do do is write a query which check the previous highest code present into my db and the incriment it to +1
for example C001 -> C002,C009->C010,C099`->C100 and so on
Similarly for SC001->SC002,SC009->SC010,SC099->SC100 and so on
Similarly fro B001 -> B002,B009->B010,B099`->B100 and so on
I have a query which my friend has suggested me to use but that query only incriminating AAAA->AAAA01 , AAAA09->AAAA10
query is
SELECT id AS PrevID, CONCAT(
SUBSTRING(id, 1, 4),
IF(CAST(SUBSTRING(id, 5) AS UNSIGNED) <= 9, '0', ''),
CAST(SUBSTRING(id, 5) AS UNSIGNED) + 1
) AS NextID
FROM (
-- since you allow strings such as AAAA20 and AAAA100 you can no longer use MAX
SELECT id
FROM t
ORDER BY SUBSTRING(id, 1, 4) DESC, CAST(SUBSTRING(id, 5) AS UNSIGNED) DESC
LIMIT 1
) x
when i am replacing ID with CategoryCode it is giving me PrevID-C004 NextID-C00401 which is not my requirement i want PrevID-C004 and NextID->C005
NOTE i am using my sqlServer 5.1
Just try this one ,
SELECT
CategoryCode,CAST(CONCAT(LPAD(CategoryCode,1,0),LPAD(MAX(RIGHT(CategoryCode,
3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
SubCategoryCode,CAST(CONCAT(LPAD(SubCategoryCode,2,0),
LPAD(MAX(RIGHT(CategoryCode, 3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
BrandCode,CAST(CONCAT(LPAD(BrandCode,1,0), LPAD(MAX(RIGHT(BrandCode, 3)) +
1, 3, 0)) AS CHAR) FROM test

MySQL Query for calculating weightage

To calculate the weightage of faults i've formulated this query,
Select id,faultdistribution, faulttype, faultseverity,
IF (faultdistribution='crs', COUNT(id) * 8, 0) +
IF (faultdistribution='configuration', COUNT(id) * 6, 0) +
IF (faulttype='bs' AND faultseverity='ft', COUNT(id) * 4, 0) +
IF (faulttype='bs' AND faultseverity='mj', COUNT(id) * 2, 0) +
IF (faulttype='bs' AND faultseverity='md', COUNT(id) * 5, 0) +
IF (faulttype='bs' AND faultseverity='mi', COUNT(id) * 3, 0) +
IF (faulttype='lf' AND faultseverity='ft', COUNT(id) * 2, 0) +
IF (faulttype='lf' AND faultseverity='mj', COUNT(id) * 1, 0)
FROM tbl_fault WHERE product='DAS' AND faultdistribution='missed'
What i intend to do is;
If Fault distribution= 'crs' then Fault * 8 + If Fault distribution= 'configuration' then Fault * 6 .........
As, there are records in database but i am not having any result from above query, help/suggestions required.
Regards
Becuase you are using Aggregate function COUNT in your query which returns only one row.But your query is running for all rows one by one which is wrong.
The COUNT() function returns the number of rows that matches a specified criteria.

Does mysql query cache the dynamically calculated columns

I have a mysql query:
SELECT my_table.* WHERE SOUNDEX(my_col)='whatever' OR SUBSTR(SOUNDEX(my_col),4)='whatever' ORDER BY SUBSTR(SOUNDEX(my_col),4)='whatever',SOUNDEX(my_col)='whatever'
How many times will the substring function and soundex functions will actually be called? I mean for exactly same inputs will mysql cache the results over the span of one query?
If not, how can I make the change in the query so that each function is called minimum times possible.
MySQL would call this function four times for every returned row, to avoid this you can use a subquery, so instead of
SELECT *
FROM song
ORDER BY Substr(pre_calculated_soundex, 1, 1) =
Substr(Soundex("aaaa"), 1, 1)
+ Substr(pre_calculated_soundex
, 2, 1) =
Substr
(Soundex("aaaa"), 2, 1)
+ Substr(pre_calculated_soundex, 3, 1)
= Substr(Soundex("aaaa"), 3, 1)
+ Substr(pre_calculated_soundex, 4, 1
)
= Substr(Soundex("aaaa"), 4, 1)
You can do
SELECT * from (select *, Soundex("aaaa") as current_soundex from song)
ORDER BY
Substr(pre_calculated_soundex, 1, 1) = Substr(current_soundex , 1, 1)
+ Substr(pre_calculated_soundex, 2, 1) = Substr(current_soundex , 2, 1)
+ Substr(pre_calculated_soundex, 3, 1) = Substr(current_soundex , 3, 1)
+ Substr(pre_calculated_soundex, 4, 1) = Substr(current_soundex , 4, 1)

Mysql Order By Problematic

Okay, I'm having some difficulties with order by. Here is the problem I need to solve:
In the database I have written every tile of a map, that is 101 x 101 big. The table has 3 columns(ID, x, y), now I gotta select all the tiles in some radious. For example, I used this query:
SELECT *
FROM tile
WHERE ((x >= -3 AND x <= 3)
AND (y >= -3 AND y <= 3))
ORDER BY x ASC, y DESC;
This query selects all tiles in radius of 3 of the given coordinate (0|0) for now.
But, it doesn't sort them the way I want it to. Basically, the output must be like this.
But this is the closest I got.
http://prntscr.com/zqjd7
Edit:
Disregard the double values, had double inputs for each coordinate. Haven't seen it.
It seems that your problem is around the ASC / DESC modificator.
But since we're here, wouldn't you prefer to use a distance formula? Something near
SELECT x, y FROM tile WHERE
(
POW(x-#var1, 2) + POW(y-#var2, 2) <= POW(3, 2)
)
ORDER BY x DESC, y ASC;
Here, given a point P (m,n), we shall know the distance to a fixed point Q (x,y) by acerting D(P,Q) = SQRT( (x-m)² + (y-n)² ). As much as it has to be less than (or equals) your desired radius (= 3), we have so SQRT( (x-m)² + (y-n)² ) <= 3, or better, (x-m)² + (y-n)² <= 3², raising both terms to its square power.
SQL-language speaking, we write POW(x-m, 2) + POW(y-n, 2) <= POW(3, 2), willing to say that the distance between (x,y) and (m,n) is last than or equal 3.
About #var, it's where you enter your input value. More specifically, they are session variables, but you don't really want to use it to perform a select; just substitute them by any number you want, e.g. you can choose the origin (0,0) by putting 0 on place of #var1 and #var2.
[Update]
Well... It's always a good idea to test your code before answering. In fact I should have suggested to order firstly by y, since we first care about ordering rows to display on screen. The following code was (finally) tested (on test DB); my last suggest is to create the following index (index_y_x):
USE `test` ;
CREATE TABLE IF NOT EXISTS `test`.`tile` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT ,
`x` INT(11) NULL DEFAULT 0 ,
`y` INT(11) NULL DEFAULT 0 ,
PRIMARY KEY (`id`) ,
INDEX `index_y_x` (`y` DESC, `x` ASC) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
INSERT tile (x,y) VALUES
(-2,-2),(-2, -1),(-2, 0),(-2, 1),(-2, 2),
(-1,-2),(-1, -1),(-1, 0),(-1, 1),(-1, 2),
(0,-2), (0, -1), (0, 0), (0, 1), (0, 2),
(1,-2), (1, -1), (1, 0), (1, 1), (1, 2),
(2,-2), (2, -1), (2, 0), (2, 1), (2, 2);
SELECT x, y FROM tile
WHERE POW(x-3, 2) + POW(y-3, 2) <= POW(3, 2)
ORDER BY y DESC, x ASC;
This returns items near the point (3,3), in a range of 3 units

MySQL - my months are current stored 0-11

I thought I ran into a bug with MySQL 5.1, but the bug was in the perl code that's creating the timestamps. perl's localtime uses 0-11 for months, but MySQL's datetime uses 1-12. So, I've got all these malformed timestamps that I need to update.
2012-00-19 09:03:30
This should be:
2012-01-19 09:03:30
The problem is that the date functions for MySQL return NULL on a 00 month. Is there a way to do this in MySQL?
EDIT: Solution =
UPDATE test_stats
SET start_time = CAST(CONCAT(SUBSTRING(start_time, 1, 5),
CAST((CAST(SUBSTRING(start_time, 6, 2) AS UNSIGNED) + 1) AS CHAR(2)),
SUBSTRING(start_time, 8, 12)) AS DATETIME);
By the way, I was using MySQL 5.1
This should work:
UPDATE MyTable
SET DateTimeField =
CAST (
SUBSTRING(DateTimeString, 1, 5) -- '2012-'
+ CAST((CAST(SUBSTRING(DateTimeString, 6, 2) AS INT) + 1) AS VARCHAR) -- '00' => '1'
+ SUBSTRING(DateTimeString, 8, 12) -- '-19 09:03:30'
AS DATETIME)
Test with this select
DECLARE #x VARCHAR(50) = '2012-00-19 09:03:30'
SELECT CAST(SUBSTRING(#x, 1, 5)
+ CAST((CAST(SUBSTRING(#x, 6, 2) AS INT) + 1) AS VARCHAR)
+ SUBSTRING(#x, 8, 12) AS DATETIME)