postgresql dynamic table name while update table in recursive query - postgresql

i have table emp1 and emp1 with same structure
i want update data on emp1 and emp2 depends on case when condition using recursive query or update storage table name dynamically.
for example.
with t as(select a.empid,case when max(a.sr_no)> max(b.sr_no) then max(a.sr_no)+1 else max(b.sr_no)+1 end as maxsr,case when max(a.sr_no)< max(b.sr_no) then 'P' else 'D' end as flag from emp1 a,emp2 b where a.empid=b.empid group by a.empid)
case when t.flag='P' then update emp1 c set sr_no=t.maxsr from t where t.empid=c.empid else update emp2 c set sr_no=t.maxsr from t where t.empid=c.empid;

Related

How to perform Grouping equivalent like Informatica?

I've an Informatica function which I want to convert into query to be getting used in Spring Batch code.
I've a table EMPLOYEE table having 15 fields (all I want in select) and Informatica has function Router which creates group based on STATUS_CD = 'A' and default (means all other records should go here - where status is other than A).
How can we do in Postgres?
I've all the employees and I want to check based using combination of EMPLOYEE_CD, EMPLOYEE_ID is unique and I want to simply return the count of it.
Query1
SELECT EMPLOYEE_CD AS EMPLOYEE_CD,
EMPLOYEE_ID AS EMPLOYEE_ID,
COUNT (*) AS CNT
FROM EMPLOYEE
GROUP BY EMPLOYEE_CD, EMPLOYEE_ID
HAVING COUNT (*) > 1;
Query 2
SELECT EMPLOYEE_ID, EMPLOYEE_NAME, EMPLOYEE_EMAIL, EMPLOYEE_PHONE, EMPLOYEE_ADDRESS, (Create Count Field here)
FROM EMPLOYEE
Query 3 - I need to group (which is my original question) or Create Columns ACTIVE, NON_ACTIVE columns as a part of query results where EMPLOYEE_STAT_CD = 'A', ACTIVE column value should say YES and EMPLOYEE_STAT_CD other than A, NON_ACTIVE should say Yes.
How can merge Query1 and Query 2 and Query 3 into single query ?
if I understood the question, your code is something like:
SELECT EMPLOYEE_ID, EMPLOYEE_NAME, EMPLOYEE_EMAIL, EMPLOYEE_PHONE, EMPLOYEE_ADDRESS,
COUNT(*)OVER(PARTITION BY EMPLOYEE_CD, EMPLOYEE_ID) AS counter_from_sql1,
CASE WHEN EMPLOYEE_STAT_CD = 'A' THEN 'YES' ELSE NULL END AS ACTIVE,
CASE WHEN EMPLOYEE_STAT_CD <> 'A' THEN 'YES' ELSE NULL END AS NON_ACTIVE
FROM EMPLOYEE;
or
SELECT * FROM (
SELECT EMPLOYEE_ID, EMPLOYEE_NAME, EMPLOYEE_EMAIL, EMPLOYEE_PHONE, EMPLOYEE_ADDRESS,
COUNT(*)OVER(PARTITION BY EMPLOYEE_CD, EMPLOYEE_ID) AS counter_from_sql1,
CASE WHEN EMPLOYEE_STAT_CD = 'A' THEN 'YES' ELSE NULL END AS ACTIVE,
CASE WHEN EMPLOYEE_STAT_CD <> 'A' THEN 'YES' ELSE NULL END AS NON_ACTIVE
FROM EMPLOYEE
) z
WHERE counter_from_sql1 > 1;

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 Variable based on Group

I need to perform an update to a field in a table with a variable, but I need the variable to change when the group changes. It is just an INTt, so for example if I The example below I want to update the record of texas with a 1 and flordia with the next number of 2:
UPDATE table
set StateNum = #Count
FROM table
where xxxxx
GROUP BY state
Group Update Variable
Texas 1
Texas 1
Florida 2
Florida 2
Florida 2
I think you should use a lookup table with the state and its number StateNum Then you should store this number instead of the name to your table.
You might use DENSE_RANK within an updateable CTE:
--mockup data
DECLARE #tbl TABLE([state] VARCHAR(100),StateNum INT);
INSERT INTO #tbl([state]) VALUES
('Texas'),('Florida'),('Texas'),('Nevada');
--your update-statement
WITH updateableCTE AS
(
SELECT StateNum
,DENSE_RANK() OVER(ORDER BY [state]) AS NewValue
FROM #tbl
)
UPDATE updateableCTE SET StateNum=NewValue;
--check the result
SELECT * FROM #tbl;
And then you should use this to get the data for your lookup table
SELECT StateNum,[state] FROM #tbl GROUP BY StateNum,[state];
Then drop the state-column from your original table and let the StateNum be a foreign key.

Postgresql: insert the same data a few times

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...

Postgresql table name or alias in SELECT and WHERE clauses without specifying column name

I have two tables:
CREATE TABLE a (id INT NOT NULL);
CREATE TABLE b (id INT NOT NULL);
INSERT INTO a VALUES (1), (2);
INSERT INTO b VALUES (1);
If I try to get records from a for which there are records in b (query 1):
SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id WHERE b is NOT NULL;
I get:
id | b
----+-----
1 | (1)
If I try to get records from a for which there are NO records in b (query 2):
SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id WHERE b IS NULL;
I get:
id | b
----+---
2 |
It seems OK.
Then I alter b:
ALTER TABLE b ADD COLUMN s TEXT NULL;
then query 1 does not return any rows, query 2 returns the same rows and
SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id;
returns
id | b
----+------
1 | (1,)
2 |
My questions are:
Why does Postresql allow to use table name or alias in WHERE clause without specifying column name?
What is (1,) in column b of resulting rows?
Why does (1,) not satisfy IS NULL and IS NOT NULL in query 1 and query 2?
P.S. If I alter table b as ALTER TABLE b ADD COLUMN s TEXT NOT NULL DEFAULT '' instead then queries 1 and 2 return the same rows.
Answering by questions:
This is row constructor, so every value from a column builds up a row value (composite value) using values from your columns for its member fields
(1,) is a row constructor with first member being 1 and second member (your text field) which has a null value, thus no value is shown.
You're comparing entire row constructor which actually satisfies both of comparison (is null and is not null)
More on point 3:
select *, b is not null as b_not_null, b is null as b_null from b;
Reult:
id | b_not_null | b_null
----+------------+--------
1 | t | f
A row IS NULL when all of its members have NULL values, otherwise it IS NOT NULL. Reproduce:
create table rowtest ( col1 int, col2 int);
insert into rowtest values (null,null), (1,1), (null,1);
select
col1, col2, rowtest,
case when rowtest is null then true else false end as rowtest_null
from rowtest;
Result:
col1 | col2 | rowtest | rowtest_null
------+------+---------+--------------
| | (,) | t
1 | 1 | (1,1) | f
| 1 | (,1) | f
Actually, for your queries they both could be rewritten to:
Query1: Get records from a with matching records from b
Using INNER JOIN which actually is the same as JOIN:
SELECT a.id, b FROM a JOIN b on a.id = b.id;
Query2: Get records from a with no matching records from b
Using NOT EXISTS instead of LEFT JOIN:
SELECT a.id
FROM a
WHERE NOT EXISTS (
SELECT 1
FROM b
WHERE a.id = b.id
);
For the last query if you really need the second empty column you can add a static value to select list like that:
SELECT a.id, null as b
The table name can be used in the SELECT or WHERE to refer to a record value containing the entire row of the table. In the output of psql a record will appear like (1) (if it has one field), or (1,2) (if it has two fields), etc. The (1,) that you see is a record with two fields that contain the values 1 and NULL. A value of record type can be null, e.g. in a left join if there is no matching row for the second table.