Round off values in 2 columns that have decimal places - mysql

Some of the value in two of my columns have decimal places for some reason, this is a bug in my code I need to sort out but its causing problems at the moment.
How can I round numbers with decimal places?
Example Data
# Table: level_3
|---------------------|
| day_start | day_end |
|-----------|---------|
| -123 | 20 |
| -650 | 234 |
| -133.042..| 104.0416|
| -581 | 123 |
|---------------------|
Expected Output
# Table: level_3
|---------------------|
| day_start | day_end |
|-----------|---------|
| -123 | 20 |
| -650 | 234 |
| -133 | 104 |
| -581 | 123 |
|---------------------|
EDIT: If it's any easier, it doesn't need to be rounded, just removed anything after and including the period.
EDIT 2: I have actually fixed my problem, I just changed the structure to INT and back which removed all the decimals! But thats for the answers, they will help others looking for this!

You have 2 simple options:
Round the values when you query the database, using ROUND, FLOOR, CEIL mysql function
e.g.:SELECT ROUND(day_start, 0) as day_start, ROUND(day_end, 0) as day_end
Round the value using php after you query the database, using round, floor or ceil

Use either the PHP floor() function, or the mysql FLOOR() function
PHP
<?php
echo floor(44.62); // will output "44"
MySQL
SELECT FLOOR(44.62);
-> 44
HOWEVER
SELECT FLOOR(-44.62);
-> -45
So, you can try something like:
SELECT IF(day_start < 0, CEIL(day_start), FLOOR(day_start)) s, IF(day_end < 0, CEIL(day_end), FLOOR(day_end)) e FROM level_3;

I'd suggest using either number_format or floor

You can try this (SQL Server)
SELECT CONVERT(INT,Day_Start), CONVERT(INT,Day_End)

SQL :
SELECT SUBSTRING (notetitle,1,4), SUBSTRING(notedescription,1,3) FROM notes

I have actually fixed my problem, I just changed the structure to INT and back which removed all the decimals! But thanks for the answers, they will help others looking for this!

Related

Mysql - XML like table with multiple values in same column

My question title is confusing, sorry about that.
I have one application that saves data in the database in XML'ish format, referencing keys and values.
The problem is that I have only one column with several values that corresponds to a certain key.
I need to have certain keys as columns but I am failing miserably to achieve that:
Below a sample of the table I have
xml_type | xml_key | xml_content_key | xml_content_value
----------------------------------------------------------------------------------------------------
Archiv::144 | 144 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 151
Archiv::144 | 144 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 5714141614
Archiv::144 | 144 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 145
So, I can run this and have all the carriers:
select xml_content_key as Carrier, xml_content_value as 'Carrier Result'
from xml_storage xs where xml_content_key LIKE '%[1]{\'Version\'}[1]{\'Carrier\'}[1]{\'Content\'}%'
But how would I other keys from column xml_content_key to be shown as coluns.
I have tried nested selects but got "Returns more than one value", a join would not apply since this is on a single table.
In short, I would like to run a query to gather a few keys from column xml_content_key and have each in a new column.
Thank you.
Without knowing the schema of either your table or your XML document I'll have to make some assumptions. But I think this isn't too hard. First I'll write out the assumptions I'm making. Please correct me if these assumptions are wrong.
It seems like you have a table in which xml_content_key is what should be the column name, and xml_key is what should be the row identifier. You only showed a very limited sample in your question, but my assumption would suggest that more data might look like this.
xml_type | xml_key | xml_content_key | xml_content_value
----------------------------------------------------------------------------------------------------
Archiv::144 | 144 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 151
Archiv::144 | 144 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 5714141614
Archiv::144 | 144 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 145
Archiv::144 | 145 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 123
Archiv::144 | 145 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 4567891234
Archiv::144 | 145 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 567
Archiv::144 | 146 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 891
Archiv::144 | 146 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 2345678912
Archiv::144 | 146 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 345
And I think you're trying to write a query to reorganize it like this.
+---------+---------+------------+-------------------+
| xml_key | Carrier | CarrierID | CustomerInterface |
+---------+---------+------------+-------------------+
| 144 | 151 | 5714141614 | 145 |
| 145 | 123 | 4567891234 | 567 |
| 146 | 891 | 2345678912 | 345 |
+---------+---------+------------+-------------------+
If I'm wrong about this part then there's no point in reading on. But if I'm right so far, then I'd like to highlight a quote from your question.
a join would not apply since this is on a single table.
You have been missing out on a great feature of SQL: self joins are extremely useful in cases like this.
It appears that there are three "content keys" (or columns) for each xml_key (or row). We will join together all the xml_content_key's that share the same xml_key, so that each row will describe a single xml_key. By the way, I'm assuming your table is named xml_storage.
SELECT xs1.xml_key AS 'xml_key',
xs1.xml_content_value AS 'Carrier',
xs2.xml_content_value AS 'CarrierID',
xs3.xml_content_value AS 'CustomerInterface'
FROM xml_storage xs1
INNER JOIN xml_storage xs2 ON xs2.xml_key = xs1.xml_key
INNER JOIN xml_storage xs3 ON xs3.xml_key = xs1.xml_key
WHERE xs1.xml_content_key LIKE "%[1]{'Version'}[1]{'Carrier'}[1]{'Content'}%"
AND xs2.xml_content_key LIKE "%[1]{'Version'}[1]{'CarrierID'}[1]{'Content'}%"
AND xs3.xml_content_key LIKE "%[1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'}%"
The basic idea here is that we separate the table into three tables and then put them back together. We put the Carriers in xs1, the CarrierIDs in xs2, and the CustomerInterfaces in xs3. Then we join these back together, putting all of the content associated with a particular xml_key on the same row.
You will probably need to alter this to fit your actual schema. In particular, this query assumes that you have exactly one Carrier, CarrierID, and CustomerInterface per unique xml_key. I am confident that this general approach will work if your data is anything like I've been assuming, but imperfect data would necessitate a more robust query than the example I've given here.
If you can share more details about your particular schema, I would be happy to edit my suggested query to fit your situation.

Truncate and Round giving more Decimals than expected in MySQL

I'm trying to take values in a Pervasive SQL database through an ODBC connection that represent dollar values and round them to the nearest cent. However whenever I run the TRUNCATE or ROUND functions, I get more digits after the decimal place than expected.
For example the command
select TRUNCATE(1234.12346345766,2), ROUND(1234.12346345766,2), TRUNCATE(ROUND(1234.12346345766,2),2);
returns the following
+------------------------------+---------------------------+---------------------------------------+
| TRUNCATE(1234.12346345766,2) | ROUND(1234.12346345766,2) | TRUNCATE(ROUND(1234.12346345766,2),2) |
+------------------------------+---------------------------+---------------------------------------+
| 1234.1199999999999 | 1234.1199999999999 | 1234.1099999999999 |
+------------------------------+---------------------------+---------------------------------------+
Where as what I would expect is something like
+------------------------------+---------------------------+---------------------------------------+
| TRUNCATE(1234.12346345766,2) | ROUND(1234.12346345766,2) | TRUNCATE(ROUND(1234.12346345766,2),2) |
+------------------------------+---------------------------+---------------------------------------+
| 1234.12 | 1234.12 | 1234.12 |
+------------------------------+---------------------------+---------------------------------------+
What can I do to fix this?
I figured it out myself but I didn't find any other post answering this exact question (please don't kill me if there is).
Looks like this is due to the values being stored as doubles rather than as decimal values (due to the limitations of the environment I'm working in I can't see the table schema.)
The solution that worked was to transform the data from DOUBLE to DECIMAL by wrapping the query in the CAST() function
select CAST(TRUNCATE(1234.12346345766,2) as DECIMAL(10,2));
select CAST(ROUND(1234.12346345766,2) as DECIMAL(10,2));
select CAST(TRUNCATE(ROUND(1234.12346345766,2),2) as DECIMAL(10,2));
With the following result
+-----------------------------------------------------+--------------------------------------------------+--------------------------------------------------------------+
| CAST(TRUNCATE(1234.12346345766,2) as DECIMAL(10,2)) | CAST(ROUND(1234.12346345766,2) as DECIMAL(10,2)) | CAST(TRUNCATE(ROUND(1234.12346345766,2),2) as DECIMAL(10,2)) |
+-----------------------------------------------------+--------------------------------------------------+--------------------------------------------------------------+
| 1234.12 | 1234.12 | 1234.11 |
+-----------------------------------------------------+--------------------------------------------------+--------------------------------------------------------------+
Which is close enough to what I wanted.

How do I store array of integers in vertica database?

Currently I'm working on vertica database.
I'm facing problem while storing array of integers in one column. I imported data values through csv.
I used the following code to create table.
CREATE TABLE testing_table_1 (email varchar,name varchar,gen int,yob int,ct int,cy int,a varchar(65000),b varchar(65000),c varchar(65000));
I imported data with the following code.
COPY testing_table_1 from '/home/naresh/Desktop/bigfile.csv' parser fcsvparser();
My sample CSV format looks like the below.
ghchnu#tly.org.cn | Donald Garcia | 2 | 2003 | 21947 | 91 | 241,127,225,68,162 | 4,84,63,69,15 | 32,44,15,31
rlmx#jyqewy.biz | Charles Brown | 2 | 2012 | 22218 | 45 | 127,156,186,136,242 | 49,69,14,80,95,1 | 39,36,38,40,20
7th,8th and 9th columns are storing in the format of a string.
But what I want is, I want them to be stored in an array of integers format.
Because of the string format I am unable to perform combination of integers operation using 'IN' query.
I don't to want to use flex-table format in vertica.
Give suggestions other than flex-table format.
Please give me a possible solution for the above problem.
Please correct me if I am doing any mistake.
Thanks in advance,
Vertica is a real, SQL based, relational database.
And those actually do not have rows with a variable number of columns - which is what using arrays would boil down to.
What you need to do is to make, out of this:
[...] 91 | 241,127,225,68,162 | 4,84,63,69,15 | 32,44,15,31
This:
[...] 91 | 1 | 241 | 4 | 32
[...] 91 | 2 | 127 | 84 | 44
[...] 91 | 3 | 225 | 63 | 15
[...] 91 | 4 | 68 | 69 | 31
[...] 91 | 5 | 162 | 15 |(null)
Check out the SPLIT_PART() function; you might want to run it with 1,2,3,4 and finally 5 as the third parameter, and use that very number as the key that you see in the second displayed column above. To get the resulting column as integers, cast the strings that come out of the SPLIT_PART() function to integers.
Good luck -
Marco

Performing boolean logic on specific multiple rows in a mysql table/view

I've searched forums for a solution, but the examples aren't making sense to me. I know my syntax is incorrect, but it's the idea I'm trying to get across.
Assuming query was ran at 2012-03-09 24:00:00. (I think I edited dummy values correctly)
task_status is a view, running = (began > ended), ran=((now()-ended) < 10h)
select * from task_status;
+----------------+---------------------+---------------------+---------+------+
| task | began | ended | running | ran |
+----------------+---------------------+---------------------+---------+------+
| MIRRORS_SPLIT | 2012-03-09 19:15:48 | 2012-03-09 19:15:51 | 0 | 1 |
| NETWORK_BACKUP | 2012-03-09 19:25:01 | 2012-03-09 19:23:41 | 0 | 1 |
| TAPE_BACKUP | 2012-03-09 19:26:01 | 2012-03-09 23:16:32 | 0 | 1 |
+----------------+---------------------+---------------------+---------+------+
I'm having issues creating a BACKUPS row, began=(MIN(NETWORK_BACKUP.began, TAPE_BACKUP.began), and end=(MAX(NETWORK_BACKUP.end, TAPE_BACKUP.end). Running and ran should evaluate correctly then, right?
I want to add a row that results as such:
| BACKUPS | 2012-03-09 19:25:01 | 2012-03-09 23:16:32 | 0 | 1 |
Any help would be greatly appreciated.
The way you use MIN() and MAX() seems wrong, remember, these are aggregate functions. They work on a set of values defined by content of the column you pass as a parameter.
It seems like you want them to tell you the MIN or MAX values of the values of began and end across two different rows, by passing two parameters. (unless I'm not understanding your pseudo syntax correctly).
Aren't you looking for something like
SELECT 'BACKUPS', MIN(began), MAX(ended)
FROM task_status WHERE task = 'NETWORK_BACKUP' OR task = 'TAPE_BACKUP'
GROUP BY task
Thank you, JustDanyul, that got me on the right track.
Here's what I ended up using.
SELECT 0 =
(
SELECT
(
(SELECT ran FROM expect.task_status WHERE task='NETWORK_BACKUP')
+
(SELECT ran FROM expect.task_status WHERE task='TAPE_BACKUP')
)
)

Why MySQL adds extra digits to floats?

I have a table of prices.
Each price is a FLOAT with two digits after the dot.
From some reason, when I use the price in IF expression, the result is the same float with many additional digits:
mysql> select price, IF(1, price,0) as my_price from tbl_prices limit 10;
+-------+------------------+
| price | my_price |
+-------+------------------+
| 79.95 | 79.9499969482422 |
| 99.95 | 99.9499969482422 |
| 89.95 | 89.9499969482422 |
| 89.95 | 89.9499969482422 |
| 79.95 | 79.9499969482422 |
| 89.95 | 89.9499969482422 |
| 89.95 | 89.9499969482422 |
| 79.95 | 79.9499969482422 |
| 79.95 | 79.9499969482422 |
| 69.95 | 69.9499969482422 |
+-------+------------------+
10 rows in set (0.00 sec)
As you can see, price looks good, however the result of IF expression that returns the same price contains garbage.
Does anybody know what is the reason for this garbage, and how can I get rid of it (without using ROUND)?
Thanks in advance!
Just don't. A float is not an exact value. Use DECIMAL fields for example for a price.
Because you can't represent the .95 in floating point. This is the closest you will get. This is why float is approximate.
If you want exact decimal places, use DECIMAL
At first you should know how the floating point works.
Fortunately mysql provides DECIMAL data type, which can specify exact precision, for example:
DECIMAL( 10, 2)
Will store 10 decimal places long number and 2 digits out of that on right side, for example:
12345678.12
1.03
and so on.