I would need to convert a binary string (actually string) column to its integer representation:
----------------------------------------------------------------
| binary_string (string) | integer (int64) <- What I need |
----------------------------------------------------------------
| '1011011100111000' | 46904 |
| '1111111111101011' | 65515 |
| '0111111001001010' | 32330 |
----------------------------------------------------------------
In my case the values are 16 bit max.
It's the equivalent to javascript code: parseInt('0111111001001010', 2)
Thanks
Consider below approach
create temp function binary2int(x string) returns int64
language js as r'''
return parseInt(x, 2);
''';
select *, binary2int(binary_string) as integer
from your_table
if applied to sample data in your question as
with your_table as (
select '1011011100111000' binary_string union all
select '1111111111101011' union all
select '0111111001001010'
)
output is
Try bqutil.fn.from_binary:
select bqutil.fn.from_binary('1011011100111000')
Related
I need to reconcile article1 (top) and article2 tables into a View displaying differences. But before that I need to drop all zeros from column 'type'. Create new ID column equals to filenumber + type so the resulting column should be use as index. All columns share same data type
Columns needed:
ID
C0016
C0029
C00311
You can utilize below script in SQL Server to get the format you want:
Reference SO post on removing padding 0
SELECT CONCAT(filenumber,type) AS filenumber, type, cost
FROM
(
SELECT
filenumber,
SUBSTRING(type, PATINDEX('%[^0]%',type),
LEN(type)- PATINDEX('%[^0]%',type)+ 1) AS type, cost
FROM
(
VALUES
('C001','00006',40),
('C002','00009',80),
('C003','00011',120)
) as t(filenumber,type, cost)
) AS t
Resultset
+------------+------+------+
| filenumber | type | cost |
+------------+------+------+
| C0016 | 6 | 40 |
| C0029 | 9 | 80 |
| C00311 | 11 | 120 |
+------------+------+------+
You can use try_convert() :
alter table table_name
add id as concat(filenumber, try_convert(int, type)) persisted -- physical storage
If you want a view :
create view veiw_name
as
select t.*, concat(filenumber, try_convert(int, type)) as id
from table t;
try_convert() will return null whereas conversation fails.
I note from the docs for BigQuery Standard SQL Mathematical functions that we can test if a number "is infinity" using the IS_INF() function something like this:
WITH demo_tbl AS (
SELECT 1 AS val UNION ALL
SELECT 100 AS val
)
SELECT
val,
IS_INF(val) as is_infinity
FROM demo_tbl
which outputs:
+---+-----+-------------+
| | val | is_infinity |
+---+-----+-------------+
| 0 | 1 | False |
| 1 | 100 | False |
+---+-----+-------------+
but is it possible to explicitly set a value to be positive or negative infinity using some constant value or key word?
Perhaps something like this:
WITH demo_tbl AS (
SELECT 1 AS val UNION ALL
SELECT +inf AS val -- <-- THIS doesnt work
)
SELECT
val,
IS_INF(val) as is_infinity
FROM demo_tbl
in order to give desired output similar to this:
+---+-----+-------------+
| | val | is_infinity |
+---+-----+-------------+
| 0 | 1 | False |
| 1 | inf | True |
+---+-----+-------------+
I searched the documentation as best as I could and had a Google around this but couldn't turn up an answer.
You can create the value using cast():
select is_inf(cast('Infinity' as float64))
or:
select is_inf(cast('inf' as float64))
Buried in the documentation is:
There is no literal representation of NaN or infinity, but the
following case-insensitive strings can be explicitly cast to float:
"NaN"
"inf" or "+inf"
"-inf"
I am trying to change the following strings into their respective numerical values, by identifying the units (millions or billions) and then multiplying accordingly. I believe I am having issues with the variable types but can't seem to find a solution. Any tips?
1.44B to 1,440,000,000
1.564M to 1,564,000
UPDATE [_ParsedXML_Key_Stats]
SET [Value] = CASE
WHEN right(rtrim([_ParsedXML_Key_Stats].[Value]),1) = 'B' And [_ParsedXML_Key_Stats].[NodeName] = 'EBITDA'
THEN substring(rtrim([_ParsedXML_Key_Stats].[Value]),1,len([_ParsedXML_Key_Stats].[Value])-1) * 1000000000
WHEN right(rtrim([_ParsedXML_Key_Stats].[Value]),1) = 'M' And [_ParsedXML_Key_Stats].[NodeName] = 'EBITDA'
THEN substring(rtrim([_ParsedXML_Key_Stats].[Value]),1,len([_ParsedXML_Key_Stats].[Value])-1) * 1000000
ELSE 0
END
With your original query I got a conversion error as the multiplication was treating the decimal value as an int, I guess you might have experienced the same problem.
One remedy that fixed it was to turn the factor into a decimal by adding .0 to it.
If you want to get the number formatted with commas you can use format function like so: FORMAT(CAST(value AS DECIMAL), 'N0') (be sure to specify appropriate length and precision for the decimal type).
Sample test data and output from SQL Fiddle below:
SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE [_ParsedXML_Key_Stats] (value VARCHAR(50), NodeName VARCHAR(50));
INSERT [_ParsedXML_Key_Stats] VALUES
('111', 'SOMETHING ELSE'),
('999', 'EBITDA'),
('47.13B', 'EBITDA'),
('1.44B', 'EBITDA'),
('1.564M', 'EBITDA');
WITH cte AS
(
SELECT
Value,
CAST(LEFT([Value],LEN([Value])-1) AS DECIMAL(28,6)) AS newValue,
RIGHT(RTRIM([Value]),1) AS c
FROM [_ParsedXML_Key_Stats]
WHERE [NodeName] = 'EBITDA'
AND RIGHT(RTRIM([Value]),1) IN ('B','M')
)
UPDATE cte
SET [Value] =
CASE
WHEN c = 'B' THEN newValue * 1000000000.0
WHEN c = 'M' THEN newValue * 1000000.0
END;
Query 1:
SELECT *, FORMAT(CAST(Value AS DECIMAL(18,0)),'N0') AS formattedValue
FROM _ParsedXML_Key_Stats
Results:
| value | NodeName | formattedValue |
|--------------------|----------------|----------------|
| 111 | SOMETHING ELSE | 111 |
| 999 | EBITDA | 999 |
| 47130000000.000000 | EBITDA | 47,130,000,000 |
| 1440000000.000000 | EBITDA | 1,440,000,000 |
| 1564000.000000 | EBITDA | 1,564,000 |
I have table A with two columns id(int) and f_value(float). Now I'd like to select all rows where f_value starts from '123'. So for the following table:
id | f_value
------------
1 | 12
2 | 123
3 | 1234
I'd like to get the second and third row. I tried to use LEFT with cast but that was a disaster. For the following query:
select f_value, str(f_value) as_string, LEFT(str(f_value), 2) left_2,
LEFT(floor(f_value), 5) flor_5, LEFT('abcdef', 5) test
from A
I got:
f_value | as_string | left_2 | flor_5 | test
------------------------------------------------
40456510 | 40456510 | | 4.045 | abcde
40454010 | 40454010 | | 4.045 | abcde
404020 | 404020 | | 40402 | abcde
40452080 | 40452080 | | 4.045 | abcde
101020 | 101020 | | 10102 | abcde
404020 | 404020 | | 40402 | abcde
The question is why left works fine for 'test' but for other returns such weird results?
EDIT:
I made another test I now I'm even more confused. For query:
Declare #f as float
set #f = 40456510.
select LEFT(cast(#f as float), LEN(4045.)), LEFT(404565., LEN(4045.))
I got:
|
------------
4.04 | 4045
Is there a default cast which causes this?
Fiddle SQL
Seems like your query is a bit wrong. The LEFT part should go in the WHERE-Clause, not the SELECT-part.
Also, just use LIKE and you should be fine:
SELECT f_value, str(f_value) as_string, LEFT(str(f_value), 2) left_2,
LEFT(floor(f_value), 5) flor_5
WHERE f_value LIKE '123%'
CREATE TABLE #TestTable(ID INT, f_value FLOAT)
INSERT INTO #TestTable
VALUES (1,22),
(2,123),
(3,1234)
SELECT *
FROM #TestTable
WHERE LEFT(f_value,3)='123'
DROP TABLE #TestTable
I hope this will help.
The replace get rid of the period in the float, by multiplying by 1 any 0 in front will be removed.
SELECT f_value
FROM your_table
WHERE replace(f_value, '.', '') * 1 like '123%'
I found the solution. The problem was that SQL Server uses the exponential representation of floats. To resolve it you need to first convert float to BigInt and then use Left on it.
Example:
Select * from A where Left(Cast(float_value as BigInt), 4) = xxxx
/*
returns significant digits from #f (a float) as an integer
negative sign is stripped off
*/
declare #num_digits int = 3; /* needs to be positive; accuracy diminishes with larger values */
with samples(num, f) as (
select 1, cast(123.45 as float) union
select 2, 123456700 union
select 3, -1.234567 union
select 4, 0.0000001234
)
select num, f,
case when f = 0 or #num_digits < 1 then 0 else
floor(
case sign(log10(abs(f)))
when -1 then abs(f) * power(10e0, -floor(log10(abs(f))) + #num_digits - 1)
when 1 then abs(f) / power(10e0, ceiling(log10(abs(f))) - #num_digits)
end
)
end as significant_digits
from samples
order by num;
sqlfiddle
Convert the FLOAT value to DECIMAL then to VARCHAR using CAST AND use LIKE to select the value starting with 4045.
Query
SELECT * FROM tbl
WHERE CAST(CAST(f_value AS DECIMAL(20,12)) AS VARCHAR(MAX)) LIKE '4045%';
Fiddle demo for reference
Does anyone know how to expand a frequency table in PostgreSQL?
For example, transform table x:
data | frequency
-------+-----------
string | 4
into
data | index
-------+-------
string | 1
string | 2
string | 3
string | 4
Set up code:
CREATE TABLE x (
data TEXT,
frequency INTEGER
);
INSERT INTO x VALUES ('string',4);
This is amazingly simple with generate_series():
SELECT data, generate_series(1, frequency) AS index
FROM x;