query sqlite: add figures any numbers and another - sqlite

I've a table "mytable" like this:
MyTable
I would like to add the figures of each number with the condition that:
if the add is > 9 you subtract 9.
Ex. 13 = 1 + 3= 4
7 = 0 + 7 = 7 55= 5 + 5=10 - 9 = 1 27 = 9
Code:
select number%9 from mytable
But, in this case, for the value 27 return 0, not 9 (value correct).
Thanks in advance

You're using mod, so your result will be in the set [0...(x-1)], where x is your divisor. You want to shift your result set to be [1...x], but not shifting everything up one. Instead, you want the result to be the "normal" mod result unless that result is zero, in which case you want to return your divisor. To do this, we'll need a case statement...
SELECT
CASE WHEN (number % 9) = 0 THEN
9
ELSE
(number % 9)
END AS [field]
FROM
mytable

Related

SQLite ORDER: Distribute result around center

Is it possible to order a SQLite select result in way that highest value is in the center and lower value are distributed around center till start and end of result set?
data set:
5
3
2
1
1
1
1
desired result:
1
1
3
5
2
1
1
Use ROW_NUMBER() window function to assign a row number to each value and with MAX() window function get the difference of each value from the max value of the table so they can be distributed around the max value:
SELECT *
FROM tablename
ORDER BY CASE WHEN ROW_NUMBER() OVER (ORDER BY col) % 2 = 1 THEN -1 ELSE 1 END *
(MAX(col) OVER () - col)
Change col to the column's name.
See the demo.

Creating even ranges based on values in an oracle table

I have a big table which is 100k rows in size and the PRIMARY KEY is of the datatype NUMBER. The way data is populated in this column is using a random number generator.
So my question is, can there be a possibility to have a SQL query that can help me with getting partition the table evenly with the range of values. Eg: If my column value is like this:
1
2
3
4
5
6
7
8
9
10
And I would like this to be broken into three partitions, then I would expect an output like this:
Range 1 1-3
Range 2 4-7
Range 3 8-10
It sounds like you want the WIDTH_BUCKET() function. Find out more.
This query will give you the start and end range for a table of 1250 rows split into 20 buckets based on id:
with bkt as (
select id
, width_bucket(id, 1, 1251, 20) as id_bucket
from t23
)
select id_bucket
, min(id) as bkt_start
, max(id) as bkt_end
, count(*)
from bkt
group by id_bucket
order by 1
;
The two middle parameters specify min and max values; the last parameter specifies the number of buckets. The output is the rows between the minimum and maximum bows split as evenly as possible into the specified number of buckets. Be careful with the min and max parameters; I've found poorly chosen bounds can have an odd effect on the split.
This solution works without width_bucket function. While it is more verbose and certainly less efficient it will split the data as evenly as possible, even if some ID values are missing.
CREATE TABLE t AS
SELECT rownum AS id
FROM dual
CONNECT BY level <= 10;
WITH
data AS (
SELECT id, rownum as row_num
FROM t
),
total AS (
SELECT count(*) AS total_rows
FROM data
),
parts AS (
SELECT rownum as part_no, total.total_rows, total.total_rows / 3 as part_rows
FROM dual, total
CONNECT BY level <= 3
),
bounds AS (
SELECT parts.part_no,
parts.total_rows,
parts.part_rows,
COALESCE(LAG(data.row_num) OVER (ORDER BY parts.part_no) + 1, 1) AS start_row_num,
data.row_num AS end_row_num
FROM data
JOIN parts
ON data.row_num = ROUND(parts.part_no * parts.part_rows, 0)
)
SELECT bounds.part_no, d1.ID AS start_id, d2.ID AS end_id
FROM bounds
JOIN data d1
ON d1.row_num = bounds.start_row_num
JOIN data d2
ON d2.row_num = bounds.end_row_num
ORDER BY bounds.part_no;
PART_NO START_ID END_ID
---------- ---------- ----------
1 1 3
2 4 7
3 8 10

Teradata : using case statement in Where clause

My question is about using case statement in where clause to check for date and assign values to columns. My sample code include.
select * from table
where
column 1 > 10 and
case when column 2 = 1
then
column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01'
else
column 4 between (1st day of this month) and (yesterday)
end ;
when I am running this code. I am getting 3706 syntax error:expected something in between field and '='.
How to fix this ?
A CASE statement will always return a value or NULL (if none of the conditions matches), so you can use it in your WHERE clause. There are a couple ways to format your CASE statement:
Format 1
CASE
WHEN <condition> THEN <some_expression>
WHEN <another_condition> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE
WHEN col1 = 10 THEN 'Y'
WHEN col1 = 20 THEN 'N'
ELSE 'N/A'
END
Format 2
CASE <expression>
WHEN <value> THEN <expression>
WHEN <another_value> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE col1
WHEN 10 THEN 'Y'
WHEN 20 THEN 'N'
ELSE 'NA'
END
I'm not sure what you're trying to do with your sample code, but it looks more like pseudo-code and will not work as-is. Your CASE statement is not formatted properly and your column references like column 1 will not work that way. If your column is actually named column 1, then you need to put double-quotes around it:
select * from table where "column 1" > 10
Can you please describe a little more clearly what exactly you are trying to do?
A CASE expression can't be used to create some kind of dynamic conditions. Write it as a bunch of AND/OR conditons:
select * from table
where
column 1 > 10 and
(
( column 2 = 1 and
(column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01')
)
or
column 4 between (1st day of this month) and (yesterday)
);
Double check the logic, the precedence of logical operators is
parenthesis
NOT
AND
OR

How to replace with zero after full-stop if not have any value using regexp_substr in oracle

Values are like:
Num(column)
786.56
35
select num,regexp_substr(num,'[^.]*') "first",regexp_substr(num,'[^.]+$') "second" from cost
when i execute the above query output will be like
num first second
786.56 786 56
35 35 35
I want to print zero if not have any value after full-stop,by default second column repeating first value
There are two options here; using either the occurrence or subexpression parameters available in REGEXP_SUBSTR().
Subexpression - the 5th parameter
Using subexpressions you can pick out which group () in your match you want to return in any given function call
SQL> with the_data (n) as (
2 select 786.56 from dual union all
3 select 35 from dual
4 )
5 select regexp_substr(n, '^(\d+)\.?(\d+)?$', 1, 1, null, 1) as f
6 , regexp_substr(n, '^(\d+)\.?(\d+)?$', 1, 1, null, 2) as s
7 from the_data;
F S
--- ---
786 56
35
^(\d+)\.?(\d+)?$ means at the start of the string ^, pick a group () of digits \d+ followed by an optional \.?. Then, pick an optional group of digits at the end of the string $.
We then use sub-expressions to pick out which group of digits you want to return.
Occurrence - the 3th parameter
If you place the number in a group and forget about matching the start and end of the string you can pick the first group of numbers and the second group of numbers:
SQL> with the_data (n) as (
2 select 786.56 from dual union all
3 select 35 from dual
4 )
5 select regexp_substr(n, '(\d+)\.?', 1, 1, null, 1) as f
6 , regexp_substr(n, '(\d+)\.?', 1, 2, null, 1) as s
7 from the_data;
F S
--- ---
786 56
35
(\d+)\.? means pick a group () of digits \d+ followed by an optional .. For the first group the first occurrence is the data before the ., for the second group the second occurrence is the data after .. You'll note that you still have to use the 5th parameter of REGEXP_SUBSTR() - subexpression - to state that you want the only the data in the group.
Both options
You'll note that neither of these return 0 when there are no decimal places; you'll have to add that in with a COALESCE() when the return value is NULL. You also need an explicit cast to an integer as COALESCE() expects consistent data types (this is best practice anyway):
SQL> with the_data (n) as (
2 select 786.56 from dual union all
3 select 35 from dual
4 )
5 select cast(regexp_substr(n, '^(\d+)\.?(\d+)?$', 1, 1, null, 1) as integer) as f
6 , coalesce(cast(regexp_substr(n, '^(\d+)\.?(\d+)?$', 1, 1, null, 2) as integer), 0) as s
7 from the_data;
F S
---- ----
786 56
35 0

generate 6 numbers between 1 and 2 in a 2:1 ratio in SQL or PL/SQL

how can i generate 6 numbers between 1 and 2 where 4 of the numbers will be 1 and the other 2 will be 2 in a random order i.e.
results
1
2
1
1
1
2
and also in a different ratio i.e. 3:2:1 for numbers between 1 and 3 for 12 numbers
i.e.
results
1
1
2
3
1
2
1
3
1
1
3
3
results don't have to be in this order but in the ratios as above in oracle SQL or PL/SQL
To get the ratios perfect you could do something like this - generate all the numbers, then sort in random order:
SELECT r
FROM (SELECT CASE
WHEN ROWNUM <=4 THEN 1
ELSE 2
END AS r
FROM DUAL
CONNECT BY LEVEL <= 6)
ORDER BY DBMS_RANDOM.value;
R
----------------------
2
1
1
2
1
1
I think this will work in straight SQL; it's horrifically inefficient, and a PL/SQL one might be less so. It's also completely static; differing ratios call for a different number of values selected.
select value
from (
select mod(value, 2) + 1 as value,
row_number() over (partition by
case mod(value, 2) = 1
then 1
else 0
end) as twos_row,
row_number() over (partition by
case mod(value, 2) = 0
then 1
else 0
end) as ones_row
from (select dbms_crypto.randominteger as value
from dba_objects
order by object_id
)
)
where twos_rows <= 2
or ones_rows <= 4
The inner-most select grabs a big stack of random numbers. The next query out determines whether that random value would be a 2 or a 1 by mod'ing the earlier random value. The last level of nesting just filters out all the rows after the correct number of that type of row has been returned.
This is untested and fragile. If you need a solution that's reliable and performance, I'd recommend PL/SQL, where you
loop
pick off random numbers
determine what partition in your set of values they'd fit into
keep them if that partition hasn't been satisfied
exit when all partitions have been satisfied.

Resources