I am trying to dynamically construct a SQLite SELECT statement that will count the number of successful & operations across several columns.
My database structure has 8 columns (named C1 through C8) Each contains a 0 or 1 in them. I have many rows of course.
I am trying to construct a SELECT statement that counts the number of successful & operations such as:
SELECT * FROM (SELECT (C1 & 1) + SELECT (C2 & 0) + SELECT (C3 & 1) + ... + SELECT (C8 & 0))
But unfortunately, this syntax does not work. The 1's and 0's in the example about are values that are dynamically determined by my application (before the SQLite stage), so I can build them into the SELECT statement as such.
Ultimately, I would like to be able to determine the row with the largest addition of the SELECT (Cx & 0). This is sort of a hamming distance function.
Can anyone see what is incorrect about my SELECT statement above? I've tried a large handful of variations, but nothing SQLite just hangs. A simple bitwise SELECT statement such as SELECT (C1 & 1) works just fine, outputting either a 0 or 1.
UPDATE:
The answer below actually does not work. If I execute the subselect statement
SELECT (C2 & 0)
it will result in a 0 regardless of value. If the value in C2 is 0, then I am trying to count that as a match, and hence a 1. Is this possible???
SELECT (C1 & 1) + (C2 & 0) + (C3 & 1) + ... + (C8 & 0) FROM MyTable
Related
I've just discovered LAG() function in PostgreSQL and I've been experimenting to see what it can achieve. I've though that I might calculate factorial with it and I wrote
SELECT i, i * lag(factorial, 1, 1) OVER (ORDER BY i, 1) as factorial FROM generate_series(1, 10) as i;
But online IDE complains that 42703 column "factorial" does not exist.
Is there any way I can access the result of previous LAG call?
You can't refer to the column recursively in its definition.
However, you can express the factorial calculation as:
SELECT i, EXP(SUM(LN(i)) OVER w)::int factorial
FROM generate_series(1, 10) i
WINDOW w AS (ORDER BY i ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
-- outputs:
i | factorial
----+-----------
1 | 1
2 | 2
3 | 6
4 | 24
5 | 120
6 | 720
7 | 5040
8 | 40320
9 | 362880
10 | 3628800
(10 rows)
Postgresql does support an advanced SQL feature called recursive query, which can also be used to express the factorial table recursively:
WITH RECURSIVE series AS (
SELECT i FROM generate_series(1, 10) i
)
, rec AS (
SELECT i, 1 factorial FROM series WHERE i = 1
UNION ALL
SELECT series.i, series.i * rec.factorial
FROM series
JOIN rec ON series.i = rec.i + 1
)
SELECT *
FROM rec;
what EXP(SUM(LN(i)) OVER w) does:
This exploits the mathematical identities that:
[1]: log(a * b * c) = log (a) + log (b) + log (c)
[2]: exp (log a) = a
[combining 1&2]: exp(log a + log b + log c) = a * b * c
SQL does not have an aggregate multiply operation, so to perform an aggregate multiply operation, we first have to take the log of each value, then we can use the sum aggregate function to give us the the log of the values' product. This we invert with the final exponentiation step.
This works as long as the values being multiplied are positive as log is undefined for 0 and negative numbers. If you have negative numbers, or zero, the trick is to check if any value is 0, then the whole aggregation is 0, and check if the number of negative values is even, then the result is positive, else it is negative. Alternatively, you could also convert the reals to the complex plane and then use the identity Log(z) = ln(r) - iπ
what ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW does
This declares an expanding window frame that includes all preceding rows, and the current row.
e.g.
when i equals 1 the values in this window frame are {1}
when i equals 2 the values in this window frame are {1,2}
when i equals 3 the values in this window frame are {1,2,3}
what is a recursive query
A recursive query lets you express recursive logic using SQL. Recursive queries are often used to generate parent-child relationships from relational data (think manager-report, or product classification hierarchy), but they can generally be used to query any tree like structure.
Here is a SO answer I wrote a while back that illustrates and explains some of the capabilities of recursive queries.
There are also a tonne of useful tutorials on recursive queries. It is a very powerful sql-language feature and solves a type of problem that are very difficult do do without recursion.
Hope this gives you more insight into what the code does. Happy learning!
For testing purposes I need to create a JSONB object with n random percentages, so that they sum up to 1.0.
Obviously, the very simple
SELECT jsonb_object(array_agg(ARRAY['prefix_' || n::TEXT, round(random()::NUMERIC, 2)::TEXT])) AS e
FROM generate_series(1,8) AS n
;
will produce numbers that won't sum up to 1.0.
I expect the solution to be much more complicated, and I can't seem to put my head around this.
How to do this in PostgreSQL 10?
You just have to adjust the values.
You could base your generator on this query:
WITH r AS (
SELECT random()
FROM generate_series(1, 8)
)
SELECT random/sum(random) OVER ()
FROM r;
WHAT I HAVE
I have a table with the following definition:
CREATE TABLE "Highlights"
(
id uuid,
chunks numeric[][]
)
WHAT I NEED TO DO
I need to query the data in the table using the following predicate:
... WHERE id = 'some uuid' and chunks[????????][1] > 10 chunks[????????][3] < 20
What should I put instead of [????????] in order to scan all items in the first dimension of the array?
Notes
I'm not entirely sure that chunks[][1] even close to something I need.
All I need is to test a row, whether its chunks column contains a two dimensional array, that has in any of its tuples some specific values.
May be there's better alternative, but this might do - you just go over first dimension of each array and testing your condition:
select *
from highlights as h
where
exists (
select
from generate_series(1, array_length(h.chunks, 1)) as tt(i)
where
-- your condition goes here
h.chunks[tt.i][1] > 10 and h.chunks[tt.i][3] < 20
)
db<>fiddle demo
update as #arie-r pointed out, it'd be better to use generate_subscripts function:
select *
from highlights as h
where
exists (
select *
from generate_subscripts(h.chunks, 1) as tt(i)
where
h.chunks[tt.i][3] = 6
)
db<>fiddle demo
My job is composed like that :
tRest >> tExtractJSonFields >> ttExtractRegexFields > (row3) > tMSSqlRow
I'm using a tExtractRegexFields compenent with 3 output variables.
The next component is a tMSSqlRow.
I would like to use tExtractRegexFields's output in my SQL query as a parameter.
My SQL Query is like that :
;WITH nums AS
(SELECT 1 AS PAGE
UNION ALL
SELECT PAGE + 1 AS value
FROM nums
WHERE nums.PAGE < "+(Integer)globalMap.get("row3.lastpage")")
INSERT INTO flight.Calendar_Page (DT_CAL, NUM_PAGE)
SELECT '2016-01-01', PAGE
FROM nums
option (maxrecursion 32767);"
"row3.lastpage" is a tExtractRegexFields's output variable.
This one is always contain NULL value.
I don't understand why globalMap.get("row3.lastpage") is null. Anyone knows how to use tExtractRegexFields's outputs ?
Thank you all
Do not use globalMap.get("row3.lastpage") in the SQL query in your tMSSqlRow, but simply concatenate row3.lastpage with your SQL string. And row3.lastpage is not a string, but row3 is a Java class in the Talend generated code and lastpage is one of its fields. This field contains the data you want to inject into the SQL statement.
globalMap.get("row3.lastpage") will always by null.
Your query should be something like:
WITH nums AS (SELECT 1 AS PAGE UNION ALL SELECT PAGE + 1 AS value FROM nums WHERE nums.PAGE < " + row3.lastpage + ") INSERT INTO flight.Calendar_Page (DT_CAL, NUM_PAGE) SELECT '2016-01-01', PAGE FROM nums option (maxrecursion 32767);
I want to shorten this result to only return rows that have a superset of all the rows and order of numbers in the chain column matters
Better to think of this as paths for example in an ltree (but dynamically generated-- in this case using a recursive cte)
si_id chain
5 {3,5}
5 {4,5}
5 {8,5}
2 {3,2}
2 {4,2}
1 {3,2,1}
1 {3,5,1}
1 {4,2,1}
1 {4,5,1}
1 {8,5,1}
edited to show expected output:
{3,2,1}
{3,5,1}
{4,2,1}
{8,5,1}
{4,5,1}
Something like this:
WITH search AS (
SELECT '{3,5,1}'::int4[] AS search,
array_upper( '{3,5,1}'::int4[], 1) AS search_len
)
SELECT *
FROM s
JOIN search ON ( chain #> search)
WHERE EXISTS (
SELECT 1
FROM generate_series(1, array_upper(chain, 1) - search_len + 1) AS i
WHERE chain[i:(search_len + i - 1)] = search
)