How to specify a limit on Postgres json_agg - sql

I want a JSON output having the distinct values of a column and also a limited number of rows.
This is the sample table that I have in a Postgres Database:
Name Author Copies Sold
---- ------- -----------
Book1 James 10
Book2 James 10
Book3 Alex 12
Book4 James 11
Book5 Amanda 1
I want to write an SQL query that returns a list of all the unique author names and also every row but with a limit of 3
This is the SQL query that I have so far
WITH first_query AS(
SELECT * FROM sample_table LIMIT 3
)
SELECT json_build_object("all_authors",json_agg(DISTINCT(author)),
"book_details",json_agg(row_to_json(first_query))
)
FROM first_query;
This gives me the following output:
{"all_authors":["James","Alex"],
"book_details":[{"name":"Book1","author":"James","copies sold":10},
{"name":"Book2","author":"James","copies sold":10},
{"name":"Book3","author":"Alex","copies sold":12}]}
In the above output, the only Authors in the list are James and Alex. However, I want the names of all three authors but still limiting "book_details" to the first three. i.e. I want Amanda to be on the list too.
Basically, this is the output I want:
{"all_authors":["James","Alex", "Amanda"],
"book_details":[{"name":"Book1","author":"James","copies sold":10},
{"name":"Book2","author":"James","copies sold":10},
{"name":"Book3","author":"Alex","copies sold":12}]}
How do I get all distinct values of a column and still have a limit on the query?

here is how you can do it;
with cte as (
SELECT * FROM books limit 3
)
SELECT json_build_object('all_authors',json_agg(DISTINCT(author)),'book_details',(select json_agg(row_to_json(cte.*,true)) from cte))
FROM books

Related

merging multiple rows into one based on id

i have the data in this format in an amazon redshift database:
id
answer
1
house
1
apple
1
moon
1
money
2
123
2
xyz
2
abc
and what i am looking for would be:
id
answer
1
house, apple, moon, money
2
123, xyz, abc
any idea? the thing is that i cannot hard code the answers as they will be variable, so preferably a solution that would simply scoop the answers for each id's row and put them together separated by a delimiter.
you can use aggregate function listagg:
select id , listagg(answer,',')
from table
group by id
You can use string_agg(concat(answer,''),',') with group by so it will be like that:
select id , string_agg(concat(answer,''),',') as answer
from table
group by id
tested here
Edit:
you don't need concatenate, you can just use string_agg(answer,',')

BigQuery INSERT SELECT results in random order of records?

I used standard SQL to insert data form one table to another in BigQuery using Jupyter Notebook.
For example I have two tables:
table1
ID Product
0 1 book1
1 2 book2
2 3 book3
table2
ID Product Price
0 5 book5 8.0
1 6 book6 9.0
2 4 book4 3.0
I used the following codes
INSERT test_data.table1
SELECT *
FROM test_data.table2
ORDER BY Price;
SELECT *
FROM test_data.table1
I got
ID Product
0 1 book1
1 3 book3
2 2 book2
3 5 book5
4 6 book6
5 4 book4
I expected it appears in the order of ID 1 2 3 4 5 6 which 4,5,6 are ordered by Price
It also seems that the data INSERT and/or SELECT FROM display records in a random order in different run.
How do I control the SELECT FROM output without including the 'Price' column in the output table in order to sort them?
And this happened when I import a csv file to create a new table, the record order is random when using SELECT FROM to display them.
The ORDER BY clause specifies a column or expression as the sort criterion for the result set.
If an ORDER BY clause is not present, the order of the results of a query is not defined.
Column aliases from a FROM clause or SELECT list are allowed. If a query contains aliases in the SELECT clause, those aliases override names in the corresponding FROM clause.
So, you most likely wanted something like below
SELECT *
FROM test_data.table1
ORDER BY Price DESC
LIMIT 100
Note the use of LIMIT - it is important part - If you are sorting a very large number of values, use a LIMIT clause to avoid resource exceeded type of error

Need help combining columns from 2 tables and keep remaining data in rows based on parameters in sql

I am needing some help with this! I have been steered toward the intersect function, but it seems limited as it only matches and returns matched values. I am trying to combine 2 tables on a common column value and return the rows based on a date parameter. Is this even possible using SQL? Thanks in advance!
My starting tables look like this:
name date doc info
janedoe 7/21 jones 47
jonwall 7/1 nick 21
name date doc info
janedoe 6/21 jones 74
jonwall 8/31 hall 22
I want to combine these rows by duplicate name. And keep the remaining data based on most recent date. so the end result should look like this.
name date doc info
janedoe 7/21 jones 47
jonwall 8/31 hall 22
Is there anyway anyone could help me on this???? I am currently using SQLExpress
WITH allRows AS (
SELECT * FROM tableA
UNION ALL
SELECT * FROM tableB
), mostRecent AS (
SELECT *,
ROW_NUMBER() OVER
(PARTITION BY name ORDER BY date DESC) as rn
FROM allRows
)
SELECT *
FROM mostRecent
WHERE rn = 1
You should have some ID column, otherwise you are risking having two person with same name.

Any built-in function in Oracle to round down numbers and distribute the remaining values randomly

I have a table say STAFF that stores the staff names and their salaries.
Below are some sample data:
STAFF | SALARY
===========================
ALEX | 100.4
JESSICA | 100.4
PETER | 99.2
The total of salaries is always a whole number and I want to round down all staff's salaries and then randomly put the remaining value to one of them.
For example, the output would be like below if JESSICA is selected to receive the remaining value.
STAFF | SALARY
===========================
ALEX | 100
JESSICA | 101
PETER | 99
Does Oracle provide any built-in function to perform the described operation.
The quantity SALARY - TRUNC(SALARY) should give the decimal portion of each salary, for each record. You can sum this for the entire table, and then increment a certain user's salary but this amount. Try something like this:
UPDATE yourTable
SET SALARY = TRUNC(SALARY) + (SELECT SUM(SALARY - TRUNC(SALARY)) FROM yourTable)
WHERE STAFF = 'JESSICA'
here I have tried one thing that gives random result based on generated random no.
with mine(STAFF,salary,status) as
(
select 'ALEX',100.4,'Y' from dual union all
select 'JESSICA',100.4,'Y' from dual union all
select 'PETER',99.2,'Y' from dual union all
select 'randomno',floor(dbms_random.value(1,4)),'N' vno from dual
)
select STAFF,decode(rndno,rno,csalary,rsalary) salary,decode(rndno,rno,'selected to receive the remaining value',null) selected from(
select rownum rno,STAFF,salary,round(salary) rsalary,ceil(salary) csalary,
(select salary from mine where status='N') rndno
from mine where status='Y'
);
here on every run on query new user is selected which have floating salary.
in above query i have add one onther rows that supply random no and compare with acual result rows.

SQL server - How to find the highest number in '<> ' in a text column?

Lets say I have the following data in the Employee table: (nothing more)
ID FirstName LastName x
-------------------------------------------------------------------
20 John Mackenzie <A>te</A><b>wq</b><a>342</a><d>rt21</d>
21 Ted Green <A>re</A><b>es</b><1>t34w</1><4>65z</4>
22 Marcy Nate <A>ds</A><b>tf</b><3>fv 34</3><6>65aa</6>
I need to search in the X column and get highest number in <> these brackets
What sort of SELECT statement can get me, for example, the number 6 like in <6>, in the x column?
This type of query generally works on finding patterns, I consider that the <6> is at the 9th position from left.
Please note if the pattern changes the below query will not work.
SELECT A.* FROM YOURTABLE A INNER JOIN
(SELECT TOP 1 ID,Firstname,Lastname,SUBSTRING(X,LEN(X)-9,1) AS [ORDER]
FROM YOURTABLE
WHERE ISNUMERIC(SUBSTRING(X,LEN(X)-9,1))=1
ORDER BY SUBSTRING(X,LEN(X)-9,1))B
ON
A.ID=B.ID AND
A.FIRSTNAME=B.FIRSTNAME AND
A.LASTNAME=B.LASTNAME