Postgresql: insert the same data a few times - postgresql

I have table a, in this table after a SQL request, I have the same records a few times.
Here is my request.
for server_id in (select bs.id from status.servers bs
join settings.config blc on bs.id = blc.server_id
where blc.lane_number = (dataitem->>'No')::SMALLINT AND blc.min_length <= (dataitem->>'len')::real
)
LOOP
insert into a(measurement_id, server_id, status)
VALUES (
measurement_id,server_id,false
);
END LOOP;
And as result i have in table a, records like:
id meas_id serv_id status
1 12 1 f
2 12 1 f
3 12 1 f
i've changed code a little, in working code there are not syntax mistakes

answering
"why i have the same records with dif id?"
table a probably have a default value for column id, so values are taken from sequence. most probably you created it with serial data type... Those results are expected then. If you want to define your value, you should not skip column in scalar list, so
insert into a(measurement_id, server_id, status)
must become
insert into a(id, measurement_id, server_id, status)
and the value passed accordingly...
If you expected one result (assuming it from same value of server_id), you need to add distinct to the
for server_id in (select distinct bs.id from status.servers bs
because currently your select returns three rows with same bs.id as result of a join with three matching rows on join key...

Related

PostgreSQL function results in inconsistent number of rows when used in WHERE clause

I have a function "experiments.get_random_experiment_group(experiment)" that when called in isolation behaves normally, but when called in a WHERE clause results in zero or more rows being returned.
For example, if I call this function like so:
SELECT
experiments.get_random_experiment_group('1a8cd547-8de6-4602-9103-3cea12f57365');
it will always return 1 of the 2 groups ids associated with that experiment.
But if I do something like this...:
SELECT
id,
experiment_id,
proportion
FROM
experiments."group"
WHERE
id = experiments.get_random_experiment_group('1a8cd547-8de6-4602-9103-3cea12f57365');
I will sometimes get 1 row, 2 rows, or no rows at all.
Why is it behaving as expected in the first case, but not in the second? Any suggestions as to what's happening?
Here is the function:
CREATE OR REPLACE FUNCTION experiments.get_random_experiment_group (experiment uuid)
RETURNS uuid
LANGUAGE plpgsql
AS
$function$
DECLARE
result uuid;
BEGIN
WITH
CTE
AS
(
SELECT
random() * (SELECT SUM(g.proportion) FROM experiments."group" g WHERE g.experiment_id = experiment) AS r
)
SELECT
id
INTO
result
FROM
(
SELECT
id,
SUM(proportion) OVER (ORDER BY id) AS s,
r
FROM
(
SELECT
*
FROM
experiments."group" g
WHERE
g.experiment_id = experiment
) a
CROSS JOIN
CTE
) q
WHERE
s >= r
ORDER BY
id
LIMIT
1;
return result;
end;
$function$;
The purpose of this function is to randomly select a group id for a given experiment id. The probability of selecting a particular group is given by the “proportion” assigned to that group.
And here are all of the groups associated with the experiment in my example:
id
experiment_id
proportion
95cc9e77-3dff-48d9-91cb-3e17c0c24d5a
1a8cd547-8de6-4602-9103-3cea12f57365
0.5
47469555-88fd-4cec-925f-9cf15b91bca0
1a8cd547-8de6-4602-9103-3cea12f57365
0.5
I am using postgres version 13.4
The function was getting called for each row in the "group" table, and thus returning rows when and only when the group id of that row happened to correspond to the randomly generated id returned by the function call.
Thanks to the commenters for pointing this out.

CASE clause statement in DB2

I have a table PROCESS . Currently it doesnt not have any records in it. I need to return one hardcoded row if the table doesnt have any record .
I am doing a select when the primary key column "id" is null then i hard code the values and return it as below
SELECT CASE WHEN p.ID IS NULL THEN 1 ELSE p.ID END ,
CASE WHEN p.COMPANY IS NULL THEN 'COMP1' ELSE p.COMPANY END
FROM PROCESS p
I took reference from the below link
If-else statement in DB2/400
But it always returns me an empty row in DB2 database and not the hardcoded values used in select statement.
08:50:27 SUCCESS SELECT 0.307 0.301 0 Empty result set fetched
08:50:29 FINISHED 0.307 0.301 0 Success: 1 Failed: 0
Please help me on this
no way to do in this way, since a primary key could never be null. and select * from empty table return no row (0 row) it do not return null.
you can do it like that:
select ID, COMPANY from PROCESS
UNION ALL
select 1 as ID, 'COMP1' as COMPANY from sysibm.sysdummy1 where (select count(*) from PROCESS) = 0;
There are various ways you could achieve what (I think) you want. This is one
SELECT
COALESCE(ID,1) AS ID
, COALESCE(COMPANY,'COMP1') AS COMPANY
FROM
TABLE(VALUES 1) AS DUMMY(D)
LEFT JOIN
PROCESS
ON
1=1

Update table with from sub select

I have two table a and b.
I want to update the row in table a that is the most recent insert for each id from the earliest insert in table b where a.id = b.id
I've been trying to use an update statement with a sub select in the from.
If I execute the sub query on its own it returns x number of rows, however when I execute the whole update statement it updated y number of rows.
update a
set title = b.title
created_at = b.created_at
from
(
select
e.id,e.title,e.created_at
from
(
select
l.id,
l.title,
l.created_at
l.t_insert
from b l
left join b r
l.id = r.id and l.t_insert > r.t_insert
) e
join
(
select
l.id,
l.title,
l.created_at,
l.t_insert
from a l
left join a r on l.report_id = r.report_id and l.t_insert <
r.t_insert
) f
)
where
a.id=b.id
I want the same number of rows to be updated as returned in the sub select query in the from.
In this case, having fewer rows updated than returned by the subquery could be because one row id is returned more than once in the subquery. If that happens, the update statement will still only update the row once. I'm assuming the statement you've provided is not exactly what you're running, but you should check that the subquery is not providing duplicates in the id field of the subquery (either using DISTINCT or GROUP BY or by double checking your JOIN conditions.

Update Multiple Columns in One Statement Based On a Field with the Same Value as the Column Name

Not sure if this is possible without some sort of Dynamic SQL or a Pivot (which I want to stay away from)... I have a report that displays total counts for various types/ various status combinations... These types and statuses are always going to be the same and present on the report, so returning no data for a specific combination yields a zero. As of right now there are only three caseTypes (Vegetation, BOA, and Zoning) and 8 statusTypes (see below).
I am first setting up the skeleton of the report using a temp table. I have been careful to name the temp table columns the same as what the "statusType" column will contain in my second table "#ReportData". Is there a way to update the different columns in "#FormattedData" based on the value of the "statusType" column in my second table?
Creation of Formatted Table (for report):
CREATE TABLE #FormattedReport (
caseType VARCHAR(50)
, underInvestigation INT NOT NULL DEFAULT 0
, closed INT NOT NULL DEFAULT 0
, closedDPW INT NOT NULL DEFAULT 0
, unsubtantiated INT NOT NULL DEFAULT 0
, currentlyMonitored INT NOT NULL DEFAULT 0
, judicialProceedings INT NOT NULL DEFAULT 0
, pendingCourtAction INT NOT NULL DEFAULT 0
, other INT NOT NULL DEFAULT 0
)
INSERT INTO #FormattedReport (caseType) VALUES ('Vegetation')
INSERT INTO #FormattedReport (caseType) VALUES ('BOA')
INSERT INTO #FormattedReport (caseType) VALUES ('Zoning')
Creation of Data Table (to populate #FormattedReport):
SELECT B.Name AS caseType, C.Name AS StatusType, COUNT(*) AS Amount
INTO #ReportData
FROM table1 A
INNER JOIN table2 B ...
INNER JOIN table3 C ...
WHERE ...
GROUP BY B.Name, C.Name
CURRENT Update Statement (Currently will be 1 update per column in #FormattedReport):
UPDATE A SET underInvestigation = Amount FROM #ReportData B
INNER JOIN #FormattedReport A ON B.CaseType LIKE CONCAT('%', A.caseType, '%')
WHERE B.StatusType = 'Under Investigation'
UPDATE A SET closed = Amount FROM #ReportData B
INNER JOIN #FormattedReport A ON B.CaseType LIKE CONCAT('%', A.caseType, '%')
WHERE B.StatusType = 'Closed'
...
REQUESTED Update Statement: Would like to have ONE update statement knowing which column to update when "#ReportData.statusType" is the same as a "#FormattedData" column's name. For my "other" column, I'll just do that one manually using a NOT IN.
Assuming I understand the question, I think you can use conditional aggregation for this:
;WITH CTE AS
(
SELECT CaseType
,SUM(CASE WHEN StatusType = 'Under Investigation' THEN Amount ELSE 0 END) As underInvestigation
,SUM(CASE WHEN StatusType = 'Closed' THEN Amount ELSE 0 END) As closed
-- ... More of the same
FROM #ReportData
GROUP BY CaseType
)
UPDATE A
SET underInvestigation = B.underInvestigation
,closed = b.closed
-- more of the same
FROM #FormattedReport A
INNER JOIN CTE B
ON B.CaseType LIKE CONCAT('%', A.caseType, '%')

Update a column of table with random entry from another table

update testdata.test
set abcd = (select abc
from DATA1
order by random()
limit 1
)
Doing this only makes one random entry from table DATA1 is getting populated in all the rows of TEST table.
What I need is - > to generate each row with random entry from DATA 1 table to TEST table
Reference the outer table from the subquery so that it becomes a correlated subquery. Then it has to be executed for every row:
UPDATE testdata.test
SET abcd = (SELECT CASE WHEN test.abcd IS NOT DISTINCT FROM test.abcd
THEN abc
END
FROM data1
ORDER BY random()
LIMIT 1
);