I made a query with the following statement :
select mood, count(*) * 100/ (select count(*) from entry)from entry group by mood having data>data-30 order by mood asc
mood is an integer from 0 to 2
the output is :
mood count
0 96,55
1 3,44
is there a way to add a row with mood 2 count 0?
SELECT MOOD, SUM (COUNTER) TOTAL
FROM ( SELECT 0 MOOD, 0 COUNTER FROM DUAL
UNION ALL
SELECT 1 MOOD, 0 COUNTER FROM DUAL
UNION ALL
SELECT 2 MOOD, 0 COUNTER FROM DUAL
UNION ALL
SELECT MOOD, COUNT ( * )
* 100.0
/ (SELECT COUNT ( * )
FROM ENTRY
WHERE DATA > DATE ('now') - 30)
FROM (SELECT *
FROM ENTRY
WHERE DATA > DATE ('now') - 30)
GROUP BY MOOD, DATA)
GROUP BY MOOD
ORDER BY MOOD ASC;
You have to enumerate (0, 1, 2, .....) all the possible numbers, associating a counter = 0.
Then, you sum the counters grouping by mood.
Please note that your condition having data>data-30 is absurd.
You have to select from ENTRY all the records satisfying the condition data > date('now') - 30, for example.
SQLite: A VIEW named "dual" that works the same as the Oracle "dual" table can be created as follows: "CREATE VIEW dual AS SELECT 'x' AS dummy;"
Related
I'm trying to calculate the distance between sequential points and partitioned by the ID number in BigQuery.
Here's what my table looks like:
OBJECTID ID DateAndTime Lat Long
1 1 2002-11-26T12:00:00 38.82551095 -109.9709871
2 1 2002-11-29T13:00:00 38.541137 -109.677575
3 2 2002-11-03T10:00:00 38.550676 -109.901774
4 2 2002-11-04T10:00:00 38.53689 -109.683531
5 2 2002-11-05T10:00:00 38.45689 -109.683531
Based on the above table, I'd want the query to calculate the distance between ObjectID 1 & 2, and then the distance between ObjectID 3 & 4 and then 4 & 5
Here's a query I've started for ordering by DateAndTime and finding the time difference. In this query I was trying to find time differences over 12hours. Is it similar logic to this? How can I calculate distances between sequenced points in BigQuery?
SELECT *,
DATETIME_DIFF( prev_DateAndTime, DateAndTime, hour) as diff_hours
FROM
(SELECT points.ID, points.DateAndTime,
LAG(DateAndTime) OVER (PARTITION BY points.ID ORDER BY points.DateAndTime) as prev_DateAndTime
FROM `table1` AS table1 INNER JOIN
`table2` AS points ON table1.ID = points.ID
WHERE
(points.DateAndTime BETWEEN table1.BeginDate AND COALESCE (table1.EndDate, CURRENT_DATE() + 1))
And points.DateAndTime between '2020-12-01T00:00:00' and CURRENT_DATE()
) d
WHERE
DATETIME_DIFF(prev_DateAndTime, DateAndTime, hour) > 12
Below example for BigQuery Standard SQL
#standardSQL
with `project.dataset.table` as (
select 1 objectid, 1 id, timestamp '2002-11-26T12:00:00' DateAndTime, 38.82551095 lat, -109.9709871 long union all
select 2, 1, '2002-11-29T13:00:00', 38.541137, -109.677575 union all
select 3, 2, '2002-11-03T10:00:00', 38.550676, -109.901774 union all
select 4, 2, '2002-11-04T10:00:00', 38.53689, -109.683531 union all
select 5, 2, '2002-11-05T10:00:00', 38.45689, -109.683531
)
select *,
objectid as objectid_start,
lead(objectid) over next as objectid_next,
round(st_distance(st_geogpoint(long, lat), lead(st_geogpoint(long, lat)) over next), 2) as distance
from `project.dataset.table`
window next as (partition by id order by DateAndTime)
-- order by id, DateAndTime
with output
I'm struggling to retrieve a "weighted probability" from a database table in my SQL statement.
What do I need to do:
I have tabular information of probable financial values like:
Table my_table
ID
P [%]
Value [$]
1
50
200
2
50
200
3
60
100
I need to calculate the weighted probability of reasonable worst case financial value to occur.
The formula is:
P_weighted = 1 - (1 - P_1 * Value_1/Max(Value_1-n) * (1 - P_2 * Value_2/Max(Value_1-n) * ...
i.e.
P_weighted = 1 - Product(1 - P_i * Value_i / Max(Value_1-n)
P_weighted = 1 - (1 - 50% * 200 / 200) * (1 - 50% * 200 / 200) * (1 - 60% * 100 / 200) = 82.5%
I know the is not product function in (Oracle) SQL, and this can be substituted by EXP( SUM LN(x))) ensuring x is always positive.
Hence, if I were only to calculate the combined probability I could (regardless of the value I could do like:
SELECT EXP(SUM(LN(1 - t.P))) FROM FROM my_table t WHERE condition
When I need to include the Max(t.Value) I've got the following problem:
A SELECT list cannot include both a group function, such as AVG, COUNT, MAX, MIN, SUM, STDDEV, or VARIANCE, and an individual column expression, unless the individual column expression is included in a GROUP BY clause.
So I tried the following:
SELECT ROUND(1-EXP(SUM(LN(1 - t.P*t.Value/max(t.Value)))),1) FROM FROM my_table t WHERE condition GROUP BY t.P, t.Value
But this does obviously group the output by probability rather than multiplying it and just returns 0.5 or 50% instead of the product which should be 0.825 or 82.5%.
How do I get the weighted probability from by table above using (Oracle) SQL?
Does this do it:
with da as (select .50 as p, 200 as v from dual union all select .50 , 200 from dual union all select .60,100 from dual),
mx as (select max(v) mx from da)
select exp(sum(ln(1-da.p*da.v/mx))) from da, mx;
EXP(SUM(LN(1-DA.P*DA.V/MX)))
----------------------------
.175
with
test1 as(
select max(value) v_max from my_table
),
test2 as(
select 1-(my.p/100* value/t1.v_max) rez
from my_table my, test1 t1
)
select to_char(round((1-(EXP (SUM (LN (rez)))))*100,2))||'%' "Weighted probability"
from test2
RESULT:
Weighted probability
--------------------
82,5%
If you want the calculation per-row then you can use an analytic SUM:
SELECT id,
ROUND(1 - EXP(SUM(LN(1 - wp)) OVER (ORDER BY id)), 3) AS cwp
FROM (
SELECT id,
p * value / MAX(value) OVER () AS wp
FROM table_name
)
Which, for the sample data:
CREATE TABLE table_name (ID, P, Value) AS
SELECT 1, .50, 200 FROM DUAL UNION ALL
SELECT 2, .50, 200 FROM DUAL UNION ALL
SELECT 3, .60, 100 FROM DUAL;
Outputs the cumulative weighted probabilities:
ID
CWP
1
.5
2
.75
3
.825
If you just want the total weighted probability then:
SELECT ROUND(1 - EXP(SUM(LN(1 - wp))), 3) AS twp
FROM (
SELECT id,
p * value / MAX(value) OVER () AS wp
FROM table_name
)
Which, for the sample data, outputs:
TWP
.825
db<>fiddle here
I'm trying to calculate the distance between sequential points and partitioned by the ID number in BigQuery.
Here's what my table looks like:
OBJECTID ID DateAndTime Lat Long
1 1 2002-11-26T12:00:00 38.82551095 -109.9709871
2 1 2002-11-29T13:00:00 38.541137 -109.677575
3 2 2002-11-03T10:00:00 38.550676 -109.901774
4 2 2002-11-04T10:00:00 38.53689 -109.683531
5 2 2002-11-05T10:00:00 38.45689 -109.683531
Based on the above table, I'd want the query to calculate the distance between ObjectID 1 & 2, and then the distance between ObjectID 3 & 4 and then 4 & 5
Here's a query I've started for ordering by DateAndTime and finding the time difference. In this query I was trying to find time differences over 12hours. Is it similar logic to this? How can I calculate distances between sequenced points in BigQuery?
SELECT *,
DATETIME_DIFF( prev_DateAndTime, DateAndTime, hour) as diff_hours
FROM
(SELECT points.ID, points.DateAndTime,
LAG(DateAndTime) OVER (PARTITION BY points.ID ORDER BY points.DateAndTime) as prev_DateAndTime
FROM `table1` AS table1 INNER JOIN
`table2` AS points ON table1.ID = points.ID
WHERE
(points.DateAndTime BETWEEN table1.BeginDate AND COALESCE (table1.EndDate, CURRENT_DATE() + 1))
And points.DateAndTime between '2020-12-01T00:00:00' and CURRENT_DATE()
) d
WHERE
DATETIME_DIFF(prev_DateAndTime, DateAndTime, hour) > 12
Below example for BigQuery Standard SQL
#standardSQL
with `project.dataset.table` as (
select 1 objectid, 1 id, timestamp '2002-11-26T12:00:00' DateAndTime, 38.82551095 lat, -109.9709871 long union all
select 2, 1, '2002-11-29T13:00:00', 38.541137, -109.677575 union all
select 3, 2, '2002-11-03T10:00:00', 38.550676, -109.901774 union all
select 4, 2, '2002-11-04T10:00:00', 38.53689, -109.683531 union all
select 5, 2, '2002-11-05T10:00:00', 38.45689, -109.683531
)
select *,
objectid as objectid_start,
lead(objectid) over next as objectid_next,
round(st_distance(st_geogpoint(long, lat), lead(st_geogpoint(long, lat)) over next), 2) as distance
from `project.dataset.table`
window next as (partition by id order by DateAndTime)
-- order by id, DateAndTime
with output
i need to generate some sample data from a population. I want to do this with an SQL query on an Oracle 11g database.
Here is a simple working example with population size 4 and sample size 2:
with population as (
select 1 as val from dual union all
select 2 from dual union all
select 3 from dual union all
select 4 from dual)
select val from (
select val, dbms_random.value(0,10) AS RANDORDER
from population
order by randorder)
where rownum <= 2
(the oracle sample() funtion didn't work in connection with the WITH-clause for me)
But now I, I want to "upscale" or multiply my sample data. So that I can get something like 150 % sample data of the population data (population size 4 and sample size 6, e.g.)
Is there a good way to achieve this with an SQL query?
You could use CONNECT BY:
with population(val, RANDOMORDER) as (
select level, dbms_random.value(0,10) AS RANDORDER
from dual
connect by level <= 6
ORDER BY RANDORDER
)
select val
FROM population
WHERE rownum <= 4;
db<>fiddle demo
The solution depends, if you want all rows from first initial set(s) and random additional rows from last one then use:
with params(size_, sample_) as (select 4, 6 from dual)
select val
from (
select mod(level - 1, size_) + 1 val, sample_,
case when level <= size_ * floor(sample_ / size_) then 0
else dbms_random.value()
end rand
from params
connect by level <= size_ * ceil(sample_ / size_)
order by rand)
where rownum <= sample_
But if you allow possibility of result like (1, 1, 2, 2, 3, 3), where some values may not appear at all in output (here 4) then use this:
with params(size_, sample_) as (select 4, 6 from dual)
select val
from (
select mod(level - 1, size_) + 1 val, sample_, dbms_random.value() rand
from params
connect by level <= size_ * ceil(sample_ / size_)
order by rand)
where rownum <= sample_
How it works? We build set of (1, 2, 3, 4) as many times as it results from division sample / size. Then we assign random values. In first case I assign 0 to first set(s), so they will be in output for sure, and random values to last set. In second case randoms are assigned to all rows.
Using the DUAL table, how can I get a list of numbers from 1 to 100?
Your question is difficult to understand, but if you want to select the numbers from 1 to 100, then this should do the trick:
Select Rownum r
From dual
Connect By Rownum <= 100
Another interesting solution in ORACLE PL/SQL:
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <= 100;
Using Oracle's sub query factory clause: "WITH", you can select numbers from 1 to 100:
WITH t(n) AS (
SELECT 1 from dual
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT * FROM t;
Do it the hard way. Use the awesome MODEL clause:
SELECT V
FROM DUAL
MODEL DIMENSION BY (0 R)
MEASURES (0 V)
RULES ITERATE (100) (
V[ITERATION_NUMBER] = ITERATION_NUMBER + 1
)
ORDER BY 1
Proof: http://sqlfiddle.com/#!4/d41d8/20837
You could use XMLTABLE:
SELECT rownum
FROM XMLTABLE('1 to 100');
-- alternatively(useful for generating range i.e. 10-20)
SELECT (COLUMN_VALUE).GETNUMBERVAL() AS NUM
FROM XMLTABLE('1 to 100');
DBFiddle Demo
If you want your integers to be bound between two integers (i.e. start with something other than 1), you can use something like this:
with bnd as (select 4 lo, 9 hi from dual)
select (select lo from bnd) - 1 + level r
from dual
connect by level <= (select hi-lo from bnd);
It gives:
4
5
6
7
8
Peter's answer is my favourite, too.
If you are looking for more details there is a quite good overview, IMO, here.
Especially interesting is to read the benchmarks.
Using GROUP BY CUBE:
SELECT ROWNUM
FROM (SELECT 1 AS c FROM dual GROUP BY CUBE(1,1,1,1,1,1,1) ) sub
WHERE ROWNUM <=100;
Rextester Demo
A variant of Peter's example, that demonstrates a way this could be used to generate all numbers between 0 and 99.
with digits as (
select mod(rownum,10) as num
from dual
connect by rownum <= 10
)
select a.num*10+b.num as num
from digits a
,digits b
order by num
;
Something like this becomes useful when you are doing batch identifier assignment, and looking for the items that have not yet been assigned.
For example, if you are selling bingo tickets, you may want to assign batches of 100 floor staff (guess how i used to fund raise for sports). As they sell a batch, they are given the next batch in sequence. However, people purchasing the tickets can select to purchase any tickets from the batch. The question may be asked, "what tickets have been sold".
In this case, we only have a partial, random, list of tickets that were returned within the given batch, and require a complete list of all possibilities to determine which we don't have.
with range as (
select mod(rownum,100) as num
from dual
connect by rownum <= 100
),
AllPossible as (
select a.num*100+b.num as TicketNum
from batches a
,range b
order by num
)
select TicketNum as TicketsSold
from AllPossible
where AllPossible.Ticket not in (select TicketNum from TicketsReturned)
;
Excuse the use of key words, I changed some variable names from a real world example.
... To demonstrate why something like this would be useful
I created an Oracle function that returns a table of numbers
CREATE OR REPLACE FUNCTION [schema].FN_TABLE_NUMBERS(
NUMINI INTEGER,
NUMFIN INTEGER,
EXPONENCIAL INTEGER DEFAULT 0
) RETURN TBL_NUMBERS
IS
NUMEROS TBL_NUMBERS;
INDICE NUMBER;
BEGIN
NUMEROS := TBL_NUMBERS();
FOR I IN (
WITH TABLA AS (SELECT NUMINI, NUMFIN FROM DUAL)
SELECT NUMINI NUM FROM TABLA UNION ALL
SELECT
(SELECT NUMINI FROM TABLA) + (LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) NUM
FROM DUAL
CONNECT BY
(LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) <= (SELECT NUMFIN-NUMINI FROM TABLA)
) LOOP
NUMEROS.EXTEND;
INDICE := NUMEROS.COUNT;
NUMEROS(INDICE):= i.NUM;
END LOOP;
RETURN NUMEROS;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NUMEROS;
WHEN OTHERS THEN
RETURN NUMEROS;
END;
/
Is necessary create a new data type:
CREATE OR REPLACE TYPE [schema]."TBL_NUMBERS" IS TABLE OF NUMBER;
/
Usage:
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10))--integers difference: 1;2;.......;10
And if you need decimals between numbers by exponencial notation:
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-1));--with 0.1 difference: 1;1.1;1.2;.......;10
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-2));--with 0.01 difference: 1;1.01;1.02;.......;10
If you want to generate the list of numbers 1 - 100 you can use the cartesian product of {1,2,3,4,5,6,6,7,8,9,10} X {0,10,20,30,40,50,60,70,80,90}
https://en.wikipedia.org/wiki/Cartesian_product
Something along the lines of the following:
SELECT
ones.num + tens.num
FROM
(
SELECT 1 num UNION ALL
SELECT 2 num UNION ALL
SELECT 3 num UNION ALL
SELECT 4 num UNION ALL
SELECT 5 num UNION ALL
SELECT 6 num UNION ALL
SELECT 7 num UNION ALL
SELECT 9 num UNION ALL
SELECT 10 num
) as ones
CROSS JOIN
(
SELECT 0 num UNION ALL
SELECT 10 num UNION ALL
SELECT 20 num UNION ALL
SELECT 30 num UNION ALL
SELECT 40 num UNION ALL
SELECT 50 num UNION ALL
SELECT 60 num UNION ALL
SELECT 70 num UNION ALL
SELECT 80 num UNION ALL
SELECT 90 num
) as tens;
I'm not able to test this out on an oracle database, you can place the dual where it belongs but it should work.
SELECT * FROM `DUAL` WHERE id>0 AND id<101
The above query is written in SQL in the database.