I have table names with name and surname columns. I want to grab random name and surname from it, i tried this, but it takes one name and surname and prints it 100 times so it makes only one select at the start and then uses it's value,how can i fix it?
SELECT (SELECT name FROM names WHERE ID = ROUND(RANDOM() * 10 + 1)),
(SELECT surname FROM names WHERE ID = ROUND(RANDOM() * 10 + 1))
FROM GENERATE_SERIES(1, 100);
In order for Postgres to evaluate the select in the subquery multiple times, it needs to look like a correlated subquery -- one whose results depend on the values being returned by the top-level query. A minor problem here is that you don't actually care about those values. You can hack around that by meaninglessly including them in the subqueries, like this:
SELECT (SELECT name FROM names WHERE ID = ROUND(RANDOM() * 10 + 1 + i - i)),
(SELECT surname FROM names WHERE ID = ROUND(RANDOM() * 10 + 1 + i - i))
FROM GENERATE_SERIES(1, 100) i;
Another approach would be to move the subqueries to your FROM clause, put a different generate_series clause in each one, and then join them on the output of each series, but that ends up being really complicated SQL.
you didn't use the generateseries in the subquery , try with this
SELECT (SELECT name FROM names WHERE ID = ROUND(RANDOM() * 10 + g)),
(SELECT surname FROM names WHERE ID = ROUND(RANDOM() * 10 + g))
FROM GENERATE_SERIES(1, 100) g;
Related
I need help to get an result.
perscarcountoffset
person
0
1
0
1
I need a Total from a count of the lines where is person 1 + sum of the cell perscarcountoffset
select SUM((select sum(perscarcountoffset) from table where person = 1) + (select count(*) from table where person = 1)) from table where person = 1;
Thanks for any idea.
Try to create a query in postgresql. This works but it gives me 4 as result. But it must be only 2.
This returns 4 because you're actually computing
(select sum(perscarcountoffset) from table where person = 1) + (select count(*) from table where person = 1)
for each row in table (where person = 1), then summing that. So you're getting 2+2.
This is because anything outside of the aggregation method (i.e. the outer SUM() here) is per-row, and the inner sub-selects returns 2 for both rows.
The query you want doesn't need to be this complicated, this should do:
SELECT SUM(perscarcountoffset) + COUNT(*)
FROM table
WHERE person = 1;
I have names table with columns id, name and last_name. So what i'm trying to do is select random name and last_name from it, i tried this:
SELECT (SELECT name FROM names WHERE ID =floor(random()* 18 + 1 + x - x)),
(SELECT last_name FROM names WHERE ID = floor(random()* 18 + 1 + x - x))
FROM GENERATE_SERIES(1, 100) as x;
But it says it returns more than one row, why and how can i fix it?
When you use your query it will generate random id for each row. Therefore it get match with multiple rows in name table. Therefore it return multiple rows for this part SELECT name FROM names WHERE ID =floor(random()* 18 + 1 + x - x)). SQL not allow more than one row to get select.
This will work. I think this is what you want.
SELECT (SELECT name FROM names WHERE ID =(select floor(random()* 18 + 1 + x - x))) ,
(SELECT last_name FROM scientist WHERE id = (select floor(random()* 18 + 1 + x - x))) FROM GENERATE_SERIES(1, 100) as x;
The volatile random() function will generate a different value for each row of your table, so none or more than one row could be selected. You can avoid that by putting random() into an uncorrelated subquery, then it will only be executed once:
SELECT name FROM names
WHERE id = floor((SELECT random())*18 + 1);
I have a CTE that i want to grab data from, but i want different types of data with the same limit from the same CTE according to different rules.
Example: fruit_cte -> (id::integer, name::text, q1::boolean, q2::boolean)
I could do something like:
SELECT * FROM (SELECT 1 as query_num, * FROM fruit_cte WHERE q1 ORDER BY name LIMIT 100) as ABC
UNION ALL
SELECT * FROM (SELECT 2 as query_num, * FROM fruit_cte WHERE q2 ORDER BY name LIMIT 100) as ABC
UNION ALL
SELECT * FROM (SELECT -1 as query_num, * FROM fruit_cte WHERE NOT q1 AND NOT q2 ORDER BY name LIMIT 100) as ABC
But this is very costly and would be nice to tie this up into 1 select. Is this even possible?
The last select is a nice to have to get data that doesn't meet the requirements but possible to go without.
PG version 11+
You could get it all without the CTE, by using window functions instead.
SELECT type, id, name, q1, q2
FROM (
SELECT
CASE WHEN q1 THEN 1 WHEN q2 THEN 2 ELSE -1 END AS type,
ROW_NUMBER() OVER (
PARTITION BY CASE WHEN q1 THEN 1 WHEN q2 THEN 2 ELSE -1 END
ORDER BY NAME
) AS row_number,
id,
name,
q1,
q2
FROM ...
)
WHERE row_number <= 100
The row_number() will count, sorted by name, and keep a separate tally for every type
I want to do conditional aggregation in Postgres. I have a table with an id column and a float items column.
The query I want to write is something like this:
SELECT ( ((SUM(items) * 3) WHERE id="123"))
+ ((SUM(items) * 2) WHERE items="124")) )
FROM mytable
And I'd like to get a single number out. So for example, if my table looked like this:
org_id items
123 10
123 3
124 12
I'd like to get back the single number 63 (i.e. 13*3 + 12*2).
I'm pretty sure I need a CASE statement, but I'm not sure how to implement it.
In PostgreSQL 9.4+:
SELECT SUM(items) FILTER (WHERE org_id = 123) * 3 +
SUM(items) FILTER (WHERE org_id = 124) * 2
FROM mytable
, or, in earlier versions,
SELECT SUM(items * CASE org_id WHEN 123 THEN 3 WHEN 124 THEN 2 END)
FROM mytable
However, if you have lots of pairs like that, it would make sense to store them in a table (rather than hardcoding) and just use this:
SELECT SUM(items * coeff)
FROM (
VALUES
(123, 3),
(124, 2)
) m (id, coeff)
JOIN mytable
USING (id)
Replace the nested query m with your actual table
I don't understand how this query works
select * from users
where id in (
select round(random() * 21e6)::integer as id
from generate_series(1, 110) -- Preserve duplicates
)
limit 100
source: https://www.periscopedata.com/blog/how-to-sample-rows-in-sql-273x-faster.html
If I try to translate in natural language, it would be:
select * from users where id in...=> select all users who have an id inside the values...
select round(random() * 21e6)::integer as id => how can you select a number, here it's like "select 3500 as id". I thought that usually you select a column like for example 'select company_name as name ???' and not 'select 15 as name'
from generate_series(1, 110)=> how can you have select 3500 as id then tell him to select 3500 from a series (1,2,3,...,108,109,110)
I really don't understand this complex query.
Can someone help me understand each step ?
You've got the right idea about the main query, but seem to mostly confused by the subquery. Let me see if I can explain:
The basic idea is that you're wanting to get 110 random numbers. You use random() to get the number, apply some math to turn it into the sort of number you're looking for, and select from generate_series to repeat the process 110 times.
Now let's break it down in detail. Let's start with a basic select statement:
select some_number from some_table;
But instead of a normal table, let's use generate_series. It's a function that returns a table with one column. This query returns 110 rows containing the numbers 1 to 110:
select generate_series from generate_series(1, 110);
It returns a number, so you could do some math on the number:
select generate_series * 2 + 3500 from generate_series(1, 110);
but what if we do this: (You'd agree it should work, right?)
select generate_series * 0 + 3500 from generate_series(1, 110);
that's exactly like saying:
select 3500 from generate_series(1, 110);
which is like saying:
select 3500::integer from generate_series(1, 110);
and, since any integer works, you could also do this:
select round(random() * 21e6)::integer from generate_series(1, 110);
Lastly, you could rename the column like so:
select round(random() * 21e6)::integer as id from generate_series(1, 110);
... and there's your query.