Equivalent of Python's Map operator in PostgreSQL - sql

I have a table in PostgreSQL DB like this.
ID, Name, scores.
10, abc,{23,19,34}
11, def, {2333,233,24}
12, ghi, {321,34}
13,hio,{}
scores in the above data model is an array or list of numbers.
Now we have to find all students who has any single score which is 19 when divided by 10. How can I achieve this?
I tried this, but it doesn't work.
SELECT * FROM students where 19 = ANY(scores)/10
Some thing like this works. But we need a better solution(using an inverted index probably) as the rows are in the order of millions.
SELECT * FROM students where 190 <= ANY(scores) < 200

In your data example there is no record that meet your condition of some value that when divided by 10 is =19. But i understand that you are sure about your condition that single number from array when divided by 10 should be equal to 19. Not sum of all or something?
First do you have gin index on score column?
Second - really single numbers in your score array will be bigger then int limit? If not bigint will just slow your queries.
Consider bigint issue and if you have to have it then, else remove ::bigint from query below
SELECT * FROM students where
scores&&array[190,191,192,193,194,195,196,197,198,199]::bigint
It is ugly but probably faster then any tries of extract all number from array first then dividing them by 10 and then comparing to 19.
If you only search score for numbers that are equal 19 after dividing by 10, just use the method of Abelisto but it will be a killer during inserting as saving function index for milions of rows and long arrays will be slow.

Related

SQL script can sum the digits of a number

I created a table with a column containing numbers listed from 1 to 100. I want to delete numbers that divide by 3 without any remainder. Who can recommend me a way (script) to do that. Only logic I could make in this problem is that if the sum of digits of a number can divide by 3 that means any number which correspond to that case could be divisible.
If you are looking to delete the rows with number divisible completely by 3, you can use built-in modulus function
You could say something like this
delete
from myTable
where colNumber%3 = 0
This query should solve your problem
DELETE FROM table WHERE (id % 3) = 0;

Query smallest number of rows to match a given value threshold

I would like to create a query that operates similar to a cash register. Imagine a cash register full of coins of different sizes. I would like to retrieve a total value of coins in the fewest number of coins possible.
Given this table:
id
value
1
100
2
100
3
500
4
500
5
1000
How would I query for a list of rows that:
has a total value of AT LEAST a given threshold
with the minimum excess value (value above the threshod)
in the fewest possible rows
For example, if my threshold is 1050, this would be the expected result:
id
value
1
100
5
1000
I'm working with postgres and elixir/ecto. If it can be done in a single query great, if it requires a sequence of multiple queries no problem.
I had a go at this myself, using answers from previous questions:
Using ABS() to order by the closest value to the threshold
Select rows until a sum reduction of a single column reaches a threshold
Based on #TheImpaler's comment above, this prioritises minimum number of rows over minimum excess. It's not 100% what I was looking for, so open to improvements if anyone can, but if not I think this is going to be good enough:
-- outer query selects all rows underneath the threshold
-- inner subquery adds a running total column
-- window function orders by the difference between value and threshold
SELECT
*
FROM (
SELECT
i.*,
SUM(i.value) OVER (
ORDER BY
ABS(i.value - $THRESHOLD),
i.id
) AS total
FROM
inputs i
) t
WHERE
t.total - t.value < $THRESHOLD;

SQLite3 Order by highest/lowest numerical value

I am trying to do a query in SQLite3 to order a column by numerical value. Instead of getting the rows ordered by the numerical value of the column, the rows are ordered alphabetically by the first digit's numerical value.
For example in the query below 110 appears before 2 because the first digit (1) is less than two. However the entire number 110 is greater than 2 and I need that to appear after 2.
sqlite> SELECT digit,text FROM test ORDER BY digit;
1|one
110|One Hundred Ten
2|TWO
3|Three
sqlite>
Is there a way to make 110 appear after 2?
It seems like digit is a stored as a string, not as a number. You need to convert it to a number to get the proper ordering. A simple approach uses:
SELECT digit, text
FROM test
ORDER BY digit + 0

Know the hidden row in LIMIT sql lite query

I am trying to analyse a sqllite database and I use these data for a bar chart. I will count and do the avg of age group by each value in each column, in this case Class with the limit of only first 100 distinct values.
An example of this table:
Age Class
25 Worker
30 Student
48 Spy
I use LIMIT 100 to limit the result. To add more information for user, I want to let user know the number of values didn't get in account and the hidden rows, is there anyway to achieve this?
Simple solution: I am not very familiar with sql so I think to do two queries, with and without LIMIT, count the number of rows and substrat each other to find the answer. But because I have 42 columns so I would be very happy if I can have another solution.
If you want all but the first 100 rows, you can combine LIMIT with OFFSET.
select * from test01 LIMIT 1000000 OFFSET 100;

SQL Server SQL Select: How do I select rows where sum of a column is within a specified multiple?

I have a process that needs to select rows from a Table (queued items) each row has a quantity column and I need to select rows where the quantities add to a specific multiple. The mulitple is the order of between around 4, 8, 10 (but could in theory be any multiple. (odd or even)
Any suggestions on how to select rows where the sum of a field is of a specified multiple?
My first thought would be to use some kind of MOD function which I believe in SQL server is the % sign. So the criteria would be something like this
WHERE MyField % 4 = 0 OR MyField % 8 = 0
It might not be that fast so another way might be to make a temp table containing say 100 values of the X times table (where X is the multiple you are looking for) and join on that