Ensure percentages are between 0 and 1, inclusive (using a single function) - sql

I have percentages in a condition table:
create table condition (percent_decimal number(3,2));
insert into condition values (-0.01);
insert into condition values (0.1);
insert into condition values (1);
insert into condition values (1.1);
commit;
PERCENT_DECIMAL
---------------
-0.01
.1
1
1.1
I want to select the values, but modify them to present them as percentages between 0 and 1 (inclusive):
Convert -0.01 to 0
Leave .1 as is
Leave 1 as is
Convert 1.1 to 1
I can successfully do this using the greatest and least functions:
select
percent_decimal,
least(1,greatest(0,percent_decimal)) as percent_modified
from
condition
PERCENT_DECIMAL PERCENT_MODIFIED
--------------- ----------------
-0.01 0
.1 .1
1 1
1.1 1
However, I'm wondering if there is a more succinct way of doing this--with a single function.

You could use a single case expression:
select
percent_decimal,
case when percent_decimal < 0 then 0
when percent_decimal > 1 then 1
else percent_decimal
end as percent_modified
from
condition
/
PERCENT_DECIMAL PERCENT_MODIFIED
--------------- ----------------
-0.01 0
.1 .1
1 1
1.1 1
which is longer, but uses no functions, and I think it's clearer to someone coming along later what your logic is.

Related

Aggregating values into previous row based on condition

I have below input table. I need to create a query to generate the output table which shown below.
The time should be accumulated and the summing up should stop when a record with both time and qty is defined and should restart from there. The Spent_Qty is the sum of all qty defined from both time and qty record till next non zero time and qty record.
Example:
first 3 rows has no meaning. 4th row has Qty defined but the next row has time defined so the qty is belong to previous time.
5th row has 3.5 (decimal time) and no Qty so need sum up with next record with qty defined. 6th row has both defined so the sum of time now is 7.25 (time / 60). 6th row has 2 qty defined and 7th row has 0 qty and 0, 8th row has no time but 0.5 qty is show. This should be summed up with 6th row which 2.5. The 9th row has hours defined so need to stop the qty accumulation and restart from here
The result:
7.25hrs took 2.5 spent qty
Example:
INPUT:
Time
Qty
0
0
0
0
0
0
0
1
3.75
0
3.5
2
0
0
0
0.5
2.5
0
2.5
0.5
0
0.5
0
0
3
0
3.5
0.4
0
0.5
1
0
3
2
0
0
0
2
0
1
4
1
1.75
0
1.75
0
0
1
0.75
1
Output
TOT_TIME
Spent QTY
7.25
2.5
5
1
6.5
0.9
4
5
4
1
3.5
1
0.75
1
I have used LEAD, LAG and other analytical functions. I need to write select statement to get the result along with few other columns. its not working out.
You can use:
SELECT *
FROM table_name
MATCH_RECOGNIZE(
ORDER BY rn
MEASURES
SUM(time) AS total_time,
SUM(qty) AS total_qty
PATTERN ( ^ no_time* | any_row*? time_and_qty no_time* )
DEFINE
time_and_qty AS time > 0 AND qty > 0,
no_time AS time = 0
)
Which, for the sample data, outputs:
TOTAL_TIME
TOTAL_QTY
0
1
7.25
2.5
5
1
6.5
.9
4
5
4
1
4.25
2
Note: The final 4 rows are aggregated together due to the rule "The time should be accumulated and the summing up should stop when a record with both time and qty is defined and should restart from there." It is not until you get to the final row that it has both time and qty.
fiddle

Achieve incremental values for a month based on value in another column and date

I’m having a scenario where I have to increment the numbers in a month.
Condition 1 : If the value in col2 is greater than 0 then expected output is 0.
Condition 2: If value in col1 is 0 then expected output should be 999.
Condition 3: If the value in col2 is 0 then increment the numbers from 1.
Note: If either condition 1 or condition 2 is satisfied while incrementing then we must increment again from 1.
Id Date Col1 col2. Expected Output
101 01/01 28 1. 0
101 01/02 43 0 1
101 01/03 46 0. 2
101 01/04 0 0. 999
101 01/05 56 0 1
101 01/06 95 5. 0
101 01/07 0 0. 999
101 01/08 65 0. 1
101 01/09 1 0. 2
101 01/10 2 0. 3
Please suggest how this can be achieved
A cumulative count plus Teradata's RESET WHEN option:
-- similar to ROW_NUMBER, but counts only zeros
case
when col1 = 0 then 999
else count(case when col2 > 0 or col1 = 0 then NULL else 1 end)
over (partition by id
order by date_
reset when col2 > 0 or col1 = 0
rows unbounded preceding)
end

Assigning bucket label to value in new column in SQL

I have a table of one column Precipitation levels in Germany called DataStore:
PRCP
5.6
10.3
0
0
3.2
7
and I would like to add another column specifying from which range it belongs to.
for example I want to define the ranges 0-5, 5-10, 10+ so my desired outcome would be:
PRCP
Label
5.6
2
10.3
3
0
1
0
1
3.2
1
7
2
Any ideas?
You may use a CASE expression:
SELECT PRCP,
CASE WHEN PRCP < 5 THEN 1
WHEN PRCP < 10 THEN 2
ELSE 3 END AS Label
FROM yourTable;

Count the number of columns that has a true value then divide it to the total number of columns

Lets assume that the table below is called Table
**---------------------------------------------
ID Col1 Col2 Col3 Col4 ... Total
--------------------------------------------
1 1 0 NULL 1 30.33
2 0 1 1 1 60.12
3 1 1 0 0 20.12
4 1 0 1 1 60.12
5 0 NULL NULL 1 10.19
6 1 1 NULL 1 90.00
7 0 0 NULL 0 0.00
--------------------------------------------**
I wanted to count and get the average number of columns that has a "true" in it. And display the total average of it in the Total Columns. For example there are 10 columns and 5 columns are true so I divide it and got 50% in total. Assuming that all of the columns that I will counting are bit and has a value of null,0 and 1. How do I achieve this one?
You could use:
SELECT
ID,
100.0*(COALESCE(Col1, 0) + COALESCE(Col2, 0) + ... + COALESCE(Col10, 0)) / 10 AS pct
FROM yourTable;

How to do this in Hive?

I have 2 questions in hive.
1. I have data like 234336899. if the last 3 digits are i.e 899 >500 it will print 999 otherwise if 899 <500 it should print 000.
Can you please tell me how to do it in hive?
I have another scenario like input as follows.
0 1 2
3 1 2
0 1 4
3 1 4
i want to print output as follows.
0 1
3 1
1 2
1 4
How to do it in Hive?
Thanks in adv,
Your first question can be solved as below:
create table sample (col1 bigint);
insert into table sample values(234336899),(234336399);
select
col1,
case when substr(col1,-3) > 500 then '999'
when substr(col1,-3) < 500 then '000'
end as case_col1
from sample;
Here the substr hive function has been used to take the last 3 digits from col1.