I need to query a table in an array column using a subquery that is returning multiple records.
If any one of the subquery ids match in the array_column. The row should be returned in the select query.
Eg:
SELECT * FROM table_a WHERE bigint_array_column IN (
SELECT id FROM table_b
)
bigint_array_column is '{1, 2, 3, 4, 5, 6}'
Eg:
subquery data is '10, 1'.
Expected output : All the record which has 10 and 1 has to be retured.
If any one of the subquery ids exists in the bigint_array_column. I want that record to be selected in the query of table_a
I know we can do it by UNNEST the column in the select query and search it with a subquery. Is there any simpler method to do this?
ANY is working if the subquery returns only one record. but not for multiple records.
Thanks in advance.
Related
I want to build a table where each row contains a string and the number of rows where that string appears as a prefix
Basically I want
select count(*) from "myTable" where tsfield ## (p||':*')::tsquery
for each value of p in an array.
How can I write a query to do this?
Unnest the array and join:
SELECT arr.p, count(*)
FROM "myTable"
JOIN unnest('{...}') AS arr(p)
ON tsfield ## (arr.p||':*')::tsquery
GROUP BY arr.p;
I have two tables(Table A and Table B) in a Postgres DB.
Both have "id" column in common. Table A has one column called "id" and Table B has three columns: "id, date, value($)".
For each "id" of Table A there exists multiple rows in Table B in the following format - (id, date, value).
For instance, for Table A with "id" as 1 if there exists following rows in Table B:
(1, 2018-06-21, null)
(1, 2018-06-20, null)
(1, 2018-06-19, 202)
(1, 2018-06-18, 200)
I would like to extract the most recent dated non-null value. For example for id - 1, the result should be 202. Please share your thoughts or let me know in case more info is required.
Here is the solution I went ahead with:
with mapping as ( select distinct table1.id, table2.value, table2.date, row_number() over (partition by table1.id order by table2.date desc nulls last) as row_number
from table1
left join table2 on table2.id=table1.id and table2.value is not null
)
select * from mapping where row_number = 1
Let me know if there is scope for improvement.
You may very well want an inner join, not an outer join. If you have an id in table1 that does not exist in table2 or that has only null values you will get NULL for both date and value. This is due to the how outer join works. What it says is if nothing in the right side table matches the ON condition then return NULL for each column in that table. So
with mapping as
(select distinct table1.id
, table2.value
, table2.date
, row_number() over (partition by table1.id order by table2.date desc nulls last) as row_number
from table1
join table2 on table2.id=table1.id and table2.value is not null
)
select *
from mapping
where row_number = 1;
See example of each here. Your query worked because all your test data satisfied the 1st condition of the ON condition. You really need test data that fails to see what your query does.
Caution: DATE and VALUE are very poor choice for a column names. Both are SQL standard reserved words, although not Postgres specifically. Further DATE is a Postgres data type. Having columns with names the same as datatype leads to confusion.
I have a jsonb column in my table - it contains array of json objects
one of fields in these objects is a date.
Now i added new column in my table of type timestamp.
And now i need statement which hepls me to update new column with most recent date value from jsonb array column af a same record.
Following statement works great on selecting most recent date from jsonb array column of certain record:
select history.date
from document,
jsonb_to_recordset(document.history) as history(date date)
where document.id = 'd093d6b0-702f-11eb-9439-0242ac130002'
order by history.date desc
limit 1;
On update i have tried following:
update document
set status_recent_change_date = subquery.history.date
from (
select id, history.date
from document,
jsonb_to_recordset(document.history) as history(date date)
) as subquery
where document.id = subquery.id
order by history.date desc
limit 1;
Last statement does not working.
demo:db<>fiddle
UPDATE document d
SET status_recent_change_date = s.date
FROM (
SELECT DISTINCT ON (id)
*
FROM document,
jsonb_to_recordset(document.history) AS history(date date)
ORDER BY id, history.date DESC
) s
WHERE d.id = s.id;
Using LIMIT would not work because you limit the entire output of your SELECT statement. But you want to limit the output of each document.id. This can be done using DISTINCT ON (id).
This result can be used to update each record using their id values.
You most likely don't need to use LIMIT command.
It is enough to do the sorting inside SUBQUERY:
UPDATE document SET status_recent_change_date = subquery.hdate
FROM (
SELECT id, history.date AS hdate
FROM document, jsonb_to_recordset(document.history) AS history(date date)
ORDER BY history.date DESC
) AS subquery
WHERE document.id = subquery.id
I have a table 'table1' with columns (id , createddate). Assume I have millions of records in it and want to copy all records older than today to 'table1_back' with same schema as table1.
I tried to run this in batch as follows but its throwing error
WITH row_batch AS (
SELECT id
FROM table1
WHERE createddate::date < NOW() LIMIT 20000 ),
delete_rows AS (
DELETE FROM table1 t
USING row_batch b
WHERE t.id = b.id RETURNING *)
INSERT INTO table1_back SELECT * FROM delete_rows;
But am getting error ERROR: INSERT has more expressions than target columns but actually its exact replica of table1.
I guess, you should try
RETURNING t.*
Error happens because columns from row_batch subquery are added to delete_rows subquery.
Given that I have a list of repeating ids that I need to fetch some additional data to populate xls spreadsheet, how can I do that. "IN" clause returns only 1 match, but I need a row for each occurrence of an Id. I looked at PIVOT, thinking I could create a select list and then do inner join.
Select m.Id, m.LegalName, m.OtherId
from MyTable m
where m.OtherId in (1,2,1,1,3,1,4,4,2,1)
You can use VALUES clause :
SELECT t.id as OtherId, m.id, m.LegalName
FROM ( VALUES (1),(2),(1),(1),(3),(1),(4),(4),(2),(1)
) t(ID) INNER JOIN
MyTable m
ON m.OtherId = t.id;