Update query to update values incrementally and then loop PostgreSQL - postgresql

I am trying to write a query which will update the following below:
id = 1 --> id_scraping_account = 1
id = 2 --> id_scraping_account = 2
id = 3 --> id_scraping_account = 3
id = 4 --> id_scraping_account = 1
id = 5 --> id_scraping_account = 2
id = 6 --> id_scraping_account = 3
The main thing I am trying to understand is the structure of the query

You can do:
select id, id%3 as id_scraping_account
from your_table;

#PabloSantaCruz - almost. That however gives the resulting sequence 1,2,0. Should be:
select id, ((id-1)%3)+1 id_scraping_account
from your_table;

Related

Update multiple fields in a table

I have been trying to update multiple fields value in transsit column in the table tracking_details.
I have a table named tracking_details and which consist of two columns id and transsit
Example tracking_details table:-
id | transsit
------------------
1 | rec
2 | rec
3 | sen
4 |
5 | rec
Here, I would like to change rec to received where id equal 1,2 and 5
And what I have done so far is:
UPDATE tracking_details
SET transsit = 'received'
WHERE id = (select id from tracking_details where transsit='rec');
Then I got the following error:
ERROR: more than one row returned by a subquery used as an expression
********** Error **********
ERROR: more than one row returned by a subquery used as an expression
SQL state: 21000
UPDATE tracking_details
SET transsit = 'received'
WHERE id IN (select id from tracking_details where transsit='rec');
For multiple row update use IN instead of = because = will always have only one row or simply you can use join.
UPDATE tracking_details a
JOIN tracking_details b
ON a.id=b.id
SET a.transsit = 'received'
Where b.transsit='rec';
Furthurmore looking at query you do it using single query
UPDATE tracking_details
SET transsit = 'received'
WHERE transsit='rec';
You can simply do an UPDATE with a WHERE clause:
UPDATE tracking_details
SET transsit = 'received'
WHERE transsit = 'rec';

How to retrieve only a single row

Shown below is part of the view view_ar_rate_detail. I am trying to retrieve the 'daily_pay_rate' having 'eff_date_from' just prior to or equal to '2018-10-01'
The query shown below retrieves all rows ... I am missing something ...cant figure out what
fac_id eff_date_from daily_pay_rate
3 1/1/2018 195.03
3 11/1/2017 195.03
3 9/1/2017 195.03
3 8/1/2017 198.23
3 2/1/2017 198.23
3 9/1/2016 198.23
3 9/1/2015 197.43
3 2/1/2015 197.43
SELECT fac_id,eff_date_from,daily_pay_rate
FROM [view_ar_rate_detail] D
where fac_id = 3
and care_level = 'RAD'
and revenue_code = 100
and payer_id = 3
and rate_type_id = 2
and eff_date_from =
(select top 1 eff_date_from
[view_ar_rate_detail]
where fac_id = D.Fac_id
and care_level = D.care_level
and revenue_code = D.revenue_code
and payer_id = D.payer_id
and rate_type_id = D.rate_type_id
and eff_date_from <= '2018-10-01'
order by eff_date_from desc)
Please disregard. I got it to work. When working with the entire view, there were a couple of fields that had to be joined to make the query unique.

How to execute an update statement with where clause having select statement

I have a table (student) with the following schema in postgres 9.5:
id | marks | division | class
1 90 A 1
2 90 B 2
3 90 B 1
I want to update divisions of student with class 1 and marks = 90 to "A".
I know I can simply use update student set division='A' where class =1 and marks=90
But this to understand how to use a select statement returning multiple rows in the query. Somethig like:
update student set division ='A' where id=(select id from student where class=1 and marks=90)
I am new to postgres. Some pointers will help.
You don't need a sub-select:
update student
set division = 'A'
where class = 1
and marks = 90;
But if you insist on using a sub-select you need an IN:
update student
set division = 'A'
where id in (select id
from student
where class = 1
and marks = 90);

Does the returning clause always execute first?

I have a many-to-many relation representing containers holding items.
I have a primary key row_id in the table.
I insert four rows: (container_id, item_id) values (1778712425160346751, 4). These rows will be identical except the aforementioned unique row_id.
I subsequently execute the following query:
delete from contains
where item_id = 4 and
container_id = '1778712425160346751' and
row_id =
(
select max(row_id) from contains
where container_id = '1778712425160346751' and
item_id = 4
)
returning
(
select count(*) from contains
where container_id = '1778712425160346751' and
item_id = 4
);
Now I expected to get 3 returned from this query, but I got a 4. Getting a 4 is the desired behavior, but it is not what was expected.
My question is: can I always expect that the returning clause executes before the delete, or is this an idiosyncrasy of certain versions or specific software?
The use of a query in returning section is allowed but not documented. For the documentation:
output_expression
An expression to be computed and returned by the DELETE command after each row is deleted. The expression can use any column names of the table named by table_name or table(s) listed in USING. Write * to return all columns.
It seems logical that the query sees the table in a state before deleting, as the statement is not completed yet.
create temp table test as
select id from generate_series(1, 4) id;
delete from test
returning id, (select count(*) from test);
id | count
----+-------
1 | 4
2 | 4
3 | 4
4 | 4
(4 rows)
The same concerns update:
create temp table test as
select id from generate_series(1, 4) id;
update test
set id = id+ 1
returning id, (select sum(id) from test);
id | sum
----+-----
2 | 10
3 | 10
4 | 10
5 | 10
(4 rows)

SQL select from a group

Suppose we have the following table data:
ID parent stage submitted
1 1 1 1
2 1 2 1
3 1 3 0
4 1 4 0
5 5 1 1
6 5 2 1
7 5 3 1
8 5 4 1
As you can see we have 2 groups (that have the same parent). I want to select the latter stage that is submitted. In the above example i want to select the ID`s 2 and 8. I am completely lost so if anyone can help it will be appreciated a lot. :)
SELECT T.ID, T.PARENT, T.STAGE
from
T,
(
select PARENT, MAX( STAGE) MAX_STAGE
from T
where SUBMITTED = 1
GROUP BY PARENT
) M
where
T.STAGE = M.MAX_STAGE
AND T.PARENT = M.PARENT
Explanation:
First, isolate the max stage for each group with submitted = 1 (the inner select).
Then, join the result with the real table, to filter out the records with no max stage.
Select Parent, max(Id)
From tbl t
Inner Join
(
Select Parent, max(Stage) as Stage
from tbl t
Where Submitted = 1
Group by Parent
) submitted
on t.Parent = submitted.parent and
t.stage = submitted.stage
Group by Parent
This should do it:
SELECT
T1.id,
T1.parent,
T1.stage,
T1.submitted
FROM
Some_Table T1
LEFT OUTER JOIN Some_Table T2 ON
T2.parent = T1.parent AND
T2.submitted = 1 AND
T2.stage > T1.stage
WHERE
T1.submitted = 1 AND
T2.id IS NULL
SELECT * FROM Table WHERE ID = 2 OR ID = 8
Is this what you want?