If using sum>100, sums under 100 will still show - mysql

I have a table with some data. Many of these data have the name ICA Supermarket with different sums for every data. If I use the following SQL query, it will also show data with the sum under 100. This applies also if I change >= '100' to a higher digit, for an example 200.
SELECT *
FROM transactions
WHERE data_name LIKE '%ica%'
AND REPLACE(data_sum, '-', '') >= '100'
If I change >= to <= no data will show at all. Here's how the table looks like:
CREATE TABLE IF NOT EXISTS `transactions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_name` tinytext NOT NULL,
`data_sum` decimal(10,2) NOT NULL
UNIQUE KEY `id` (`id`)
)
Is it because data_sum is a DECIMAL? How can I prevent this from happening? I want to use DECIMAL for sums :)
Note: data_sum will also contain sums that are above minus.

REPLACE(data_sum, '-', '') returns a string. Also '100' is a string. So a string compare will be used. You should use ABS function:
SELECT *
FROM transactions
WHERE data_name LIKE '%ica%'
AND ABS(data_sum) >= 100

Are you looking for values >= 100 and <= -100? Or just values <= -100.
If the latter, then
... AND data_sum <= -100
This applies to DECIMAL, INT, FLOAT, etc.
Every table 'needs' a PRIMARY KEY. Promote that UNIQUE to PRIMARY.

Related

Multiply by percentage

I have a table in my database with 2 rows, Level, and Experience.
CREATE TABLE `player_xp_for_level` (
`Level` TINYINT(3) UNSIGNED NOT NULL,
`Experience` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`Level`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
;
The level experience up to level 80 have been filled in by a predefined index.
However I would like the stats for level 81 to be based on the experience of level 80 but just multiplied by *1.0115
Basically I'm looking for a query that inserts one row at a time.
Checks the previous Experience, and then modifies it and inserts it.
Workflow:: Checks previous row, updates values (previous experience*1.0115) and inserts.
If you want only to show higher score without affecting data in the database. You could use CASE expression in the SELECT statement:
SELECT player, lvl,
CASE
WHEN lvl BETWEEN 80 AND 255 THEN score * 1.0115
ELSE score
END as score
FROM player_xp_for_level
As you have posted additional info, I've updated my answer with the INSERT statement. There also you could use CASE expression in following:
INSERT INTO player_xp_for_level (lvl, score)
VALUES (#lvl, CASE WHEN #lvl BETWEEN 80 AND 255 THEN #score * 1.0115 ELSE #score END);
Assuming the structure of your table, which isn't clear from the question, then something like this?
UPDATE
player_xp_for_level
SET
xp = xp * 1.0115
WHERE
player_level BETWEEN 80 AND 255;
From the minimum code you provided, I think this is what you want:
UPDATE player_xp_for_level
SET name_of_value_column = name_of_value_column * 1.0115
WHERE name_of_level_column BETWEEN 80 AND 255;

MySQL - get date column from a table

I have a MySQL db with a MappingTable which consists of two columns. First column is a date column and another is ID - Autoincrement int column. I created this table for mapping dates and the ID's. When I query the date column with dates to retrieve the ID, no rows are getting selected. Any reason?
I tried
date_format in the SELECT query
str_to_date while checking in the WHERE clause
Compared like current_date > "2016-07-12" AND current_date <= "2016-07-12"
IfI compare LIKE "2016-07-1%" I'm getting matching rows but if I select "2016-07-12%" though there are matching rows, it is giving 0 rows.
I defined my column as DATE only.
Anything I'm missing here?
CREATE TABLE `mapping_table` (
`Current_date` date DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;
My question is, I want to select something like this.
select id from mapping_table where current_date="2016-07-12";
I tried with all approaches as mentioned above, but no rows are not retrieving.
use back tick on columns and table names so it wont be read/parse as keyword.
select `id` from `mapping_table` where `current_date` = "2016-07-12";
In the sample you provided you should use a date_format
select id from mapping_table where current_date= DATE_FORMAT("2016-07-12",'%Y-%d-%m') ;
or use a range
select id from mapping_table where current_date
BETWEEN DATE_FORMAT("2016-07-12",'%Y-%d-%m')
and DATE_FORMAT("2016-07-10",'%Y-%d-%m')

SQL - CURDATE() + 4 random digits (2013-10-02-0001)

create table Table1(
DateIdentify CHAR(15),
primary key(DateIdentify)
);
Insert into Table1 (DateIdentify) VALUES('?');
How I want the 'DateIdentify' to look: (20131002-0001) with 0001 being some sort of an auto incrementer that starts at 0001 and goes up every insert and 20131002 coming from CURDATE(), so adding CURDATE() + 4 digits. I'm wondering if this is possible? If so, could anyone please point me in the right direction?
EDIT:
CREATE TABLE Table1(
IdTable1 int auto_increment NOT NULL,
Date1 datetime,
);
You have to separate your datetime and the auto increment field.
Create your table like this using an auto-increment int field, and your datetime.
For example:
CREATE TABLE Table1(
IdTable1 int PRIMARY KEY IDENTITY(1,1) NOT NULL,
Date datetime
)
Then, you don't have to insert anything in IdTable1 because of it is auto-incremented thanks to keyword IDENTITY (SQL do the auto-increment for you)
NOTE : I wrote this for SQLServer, if you use another database, the code can change a little bit.
Which one do you use ?
EDIT :
You can also do some insert like this :
INSERT INTO Table1
(
Date
)
VALUES
(
'2013-10-02'
)
In case a solution is required as, having only one column with values in desired format you can create a function as:
create function dbo.fn_GetDateIdentify ()
returns varchar(15)
as
begin
declare #DateIdentify varchar(15);
select #DateIdentify =
(select convert (varchar(8),GETDATE (),112) +
'-' +
right ('00000' + cast (
(
(
case when Not exists (select ROW_NUMBER() over( order by (select 1)) from Table1 ) then 1
else (select top 1 ROW_NUMBER() over( order by (select 1)) as currentRownumber from Table1 order by currentRownumber desc) + 1
end
)
)
as varchar(4))
,4));
return #DateIdentify;
end
go;
and then use the function in insert statement as :
insert into Table1 (DateIdentify)
select dbo.fn_GetDateIdentify();
Hope this helps!

Greater Than and Less than MySql query failing with decimal field

I have a database which has 3 columns:
user_id | lat | lon
1 |-1.403976 | 53.428692
2 |-1.353276 | 55.224692
etc etc
Both lat and lon are set as decimal fields. I'm running a query similar to this but it isn't filtering based on being greater than and less than the given lat/lon numbers:
SELECT * FROM `table` WHERE `lat` < '-1.399999' AND 'lat' > '-1.300000'
AND 'lon' < '55.555555' AND > '53.000000'
This query just returns every row in the table and I don't know why? Is it something to do with the fields being set as decimals?
I hope someone can help - i know its probably a simple answer if you know it.
As per comment - here's the create table:
CREATE TABLE IF NOT EXISTS `members` (
`user_id` int(10) NOT NULL AUTO_INCREMENT,
`lat` decimal(8,6) NOT NULL,
`lon` decimal(8,6) NOT NULL,
UNIQUE KEY `user_id` (`user_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=136 ;
the problem is you are wrapping column names with single quotes forcing decimal values to compare against string literals. Column names as well as tables name are identifiers not string literals so they shouldn't be wrap with single quotes.
AND `lat` > '-1.300000'
AND `lon` BETWEEN '55.555555' AND '53.000000' -- use between here
As #JW suggests, you're mixing up backticks (`) and single quotes ('). Use backticks around database table and column names, but quotes around data values.
Also, the second half of your query doesn't match the first half. You have
`lat` < '-1.399999' AND 'lat' > '-1.300000'
'lon' < '55.555555' AND > '53.000000'
But it should be
`lat` < '-1.399999' AND `lat` > '-1.300000'
`lon` < '55.555555' AND `lon` > '53.000000'
So you're missing the column name in the fourth statement there.
Or, as #JW says, use BETWEEN which makes it easier to read too!
SELECT * FROM `table` WHERE `lat` BETWEEN '-1.399999' AND '-1.300000' AND `lon` BETWEEN '55.555555' AND '53.000000';
Example:
Query the sum of Northern Latitudes (LAT_N) from STATION having values greater than 38.7880 and less than 137.2345. Truncate your answer to 4 decimal places.
SELECT TRUNCATE(SUM(LAT_N),4)
FROM STATION
WHERE LAT_N > 38.7880 and LAT_N < 137.2345;
The question is pretty straight forward and your developed query need to use one of the attribute: LAT_N.
The lowest and highest value for LAT_N is given in the question. BETWEEN function will help you get the value between the highest and lowest value of LAT_N and ROUND function will get us value rounded to desired decimals(4 in this case).
My query will be as follows:
SELECT ROUND(SUM(LAT_N),4)
FROM STATION
WHERE LAT_N BETWEEN 38.7880 AND 137.2345;

adding '1' returns "BLOB"

A JobID goes as follows: ALC-YYYYMMDD-001. The first three are a companies initials, the last three are an incrementing number that resets daily and increments throughout the day as jobs are added for a maximum of 999 jobs in a day; it is these last three that I am trying to work with.
I am trying to get a before-insert trigger to look for the max JobID of the day, and add one so I can have the trigger derive the proper JobID. For the first job, it will of course return null. So here is what I have so far.
Through the following I can get a result of '000'.
set #maxjobID =
(select SUBSTRING(
(Select MAX(
SUBSTRING((Select JobID FROM jobs WHERE SUBSTRING(JobID,5,8)=date_format(curdate(), '%Y%m%d')),4,12)
)
),14,3)
);
select lpad((select ifnull(#maxjobID,0)),3,'0')
But I really need to add one to this keeping the leading zeros to increment the first and subsequent jobs of the day. My problem is as soon as try to add '1' I get a return of 'BLOB'. That is:
select lpad((select ifnull(#maxjobID,0)+1),3,'0')
returns 'BLOB'
I need it to return '001' so I can concatenate that result with the CO initials and the current date.
try casting VARCHAR back to INTEGER
SELECT lpad(SELECT (COALESCE(#maxjobID,0, CAST(#maxjobID AS SIGNED)) + 1),3,'0')
If you're using the MyISAM storage engine, you can implement exactly this with AUTO_INCREMENT, without denormalising your data into a delimited string:
For MyISAM tables, you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.
In your case:
Normalise your schema:
ALTER TABLE jobs
ADD initials CHAR(3) NOT NULL FIRST,
ADD date DATE NOT NULL AFTER initials,
ADD seq SMALLINT(3) UNSIGNED NOT NULL AFTER date,
;
Normalise your existing data:
UPDATE jobs SET
initials = SUBSTRING_INDEX(JobID, '-', 1),
date = STR_TO_DATE(SUBSTRING(JobID, 5, 8), '%Y%m%d'),
seq = SUBSTRING_INDEX(JobID, '-', -1)
;
Set up the AUTO_INCREMENT:
ALTER TABLE jobs
DROP PRIMARY KEY,
DROP JobID,
MODIFY seq SMALLINT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY(initials, date, seq)
;
You can then recreate your JobID as required on SELECT (or even create a view from such a query):
SELECT CONCAT_WS(
'-',
initials,
DATE_FORMAT(date, '%Y%m%d'),
LPAD(seq, 3, '0')
) AS JobID,
-- etc.
If you're using InnoDB, whilst you can't generate sequence numbers in this fashion I'd still recommend normalising your data as above.
So, I found a query that works (thus far).
Declare maxjobID VARCHAR(16);
Declare jobincrement SMALLINT;
SET maxjobID =
(Select MAX(
ifnull(SUBSTRING(
(Select JobID FROM jobs WHERE SUBSTRING(JobID,5,8)=date_format(curdate(), '%Y%m%d')),
5,
12),0)
)
);
if maxjobID=0
then set jobincrement=1;
else set jobincrement=(select substring(maxjobID,10,3))+1;
end if;
Set NEW.JobID=concat
(New.AssignedCompany,'-',date_format(curdate(), '%Y%m%d'),'-',(select lpad(jobincrement,3,'0')));
Thanks for the responses! Especially eggyal for pointing out the auto_increment capabilities in MyISAM.