How to perform Grouping equivalent like Informatica? - postgresql

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;

Related

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 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, '%')

How to conditionally group into column without using FULL OUTER JOIN

I want to turn
TABLEA:
id type amount
A 'Customer' 100
A 'Parter' 10
A 'Customer' 200
A 'Parter' 20
B 'Parter' 555
I can hardcode the type, don't need to be dynamic, these types are enum
RESULT:
id customer_array customer_sum partner_array partner_sum
A [100, 200] 300 [10, 20] 30
B [] 0 [555] 555
Right now
I am using two aggregate function
WITH customer AS (
SELECT
table_A,
json_agg(row_to_json(amount)) AS customer_array,
sum(amount) AS customer_sum
FROM table_A WHERE type='Customer'
GROUP BY id
), partner AS (
SELECT
table_A,
json_agg(row_to_json(amount)) AS partner_array,
sum(amount) AS partner_sum
FROM table_A WHERE type='Partner'
GROUP BY id
) SELECT
id,
COALESCE(customer_array, '[]') AS customer_array,
COALESCE(customer_sum, 0) AS customer_sum,
COALESCE(partner_array, '[]') AS partner_array,
COALESCE(partner_sum, 0) AS partner_sum
FROM customer FULL OUTER JOIN partner USING (id)
I am wondering if there is a way to achieve what I want without querying twice?
This is a simple conditional aggregation as far as I can tell:
select id,
array_agg(amount) filter (where type = 'Customer') as customer_array,
sum(amount) filter (where type = 'Customer') as customer_sum,
array_agg(amount) filter (where type = 'Partner') as partner_array,
sum(amount) filter (where type = 'Partner') as partner_sum
from table_a
group by id;
If you want an empty array instead of a NULL value, wrap the aggregation functions into a coalesce():
select id,
coalesce((array_agg(amount) filter (where type = 'Customer')),'{}') as customer_array,
coalesce((sum(amount) filter (where type = 'Customer')),0) as customer_sum,
coalesce((array_agg(amount) filter (where type = 'Partner')),'{}') as partner_array,
coalesce((sum(amount) filter (where type = 'Partner')),0) as partner_sum
from table_a
group by id;
You can try using the case statement.
https://www.postgresql.org/docs/8.2/static/functions-conditional.html
I don't have a postgres server to try this. But overall the syntax should be as below.
SELECT
table_A,
case
when Type='Customer'
then json_agg(row_to_json(amount))
else []
end AS customer_array,
case
when Type='Customer'
sum(amount)
else 0
end
AS customer_sum,
case
when Type='Partner'
then json_agg(row_to_json(amount))
else []
end AS partner_array
case
when Type='Partner'
sum(amount)
else 0
end
From table_A
GROUP BY id

Return row(s) when no values are found in the query

I have a table MyTable that is populated by BizTalk from two outside agencies (AGC1 and AGC2) every day. I have recently run into a problem where AGC2 has been sending a blank file, so no records get updated.
I need to run a query like below, that would return
AGC1 01/28/2016
AGC2 NULL
But since I have no records for AGC2 I only get
AGC1 01/28/2016
How can I get AGC2 NULL as in the first resultset?
SELECT Agency, MAX(CONVERT(nvarchar(30), DATEENTERED, 101)), Case when MAX(CONVERT(nvarchar(30), DATEENTERED, 101)) = CONVERT(nvarchar(30), GETDATE(), 101) THEN 'True' ELSE 'False' end
FROM DBO.MYTABLE
GROUP BY AGENCY
Have another table containing:
NameTable
Name
-----
AGC1
AGC2
Then use this query:
Select n.Name, max(m.dateentered)
from MyTable m right join NameTable n
on m.Agency = n.Name
group by n.Name
A RIGHT JOIN with a table containing all agencies should do the trick. This version uses a derived table with VALUES:
SELECT
ag.Agency,
MAX(CONVERT(nvarchar(30), mt.DATEENTERED, 101)),
Case when MAX(CONVERT(nvarchar(30), mt.DATEENTERED, 101)) = CONVERT(nvarchar(30), GETDATE(), 101) THEN 'True' ELSE 'False' end
FROM
DBO.MYTABLE AS mt
RIGHT JOIN ( VALUES('AGC1'),('AGC2') ) AS ag(Agency) ON
ag.Agency=mt.Agency
GROUP BY
ag.AGENCY

Updating a CTE table fail cause of derived or constant field

I'm using MS-SQL 2012
WITH C1
(
SELECT ID, 0 as Match, Field2, Count(*)
FROM TableX
GROUP BY ID, Fields2
)
UPDATE C1 SET Match = 1
WHERE ID = (SELECT MATCHING_ID FROM AnotherTable WHERE ID = C1.ID)
This TSQL statement gives me the following error:
Update or insert of view or function 'C1' failed because it contains a derived or constant field.
Ideally I would like to create a "fake field" named Match and set its default value to 0. Then with the update I would like to Update ONLY the records that have an existing entry on the "AnotherTable".
Any thoughts what am I doing wrong?
Thanks in advanced.
Try doing a Left Outer Join like
SELECT x.ID, ISNULL(a.Matching_ID, 0) as Match, x.Field2, Count(*)
FROM TableX x
LEFT OUTER JOIN AnotherTable a on x.ID = a.ID
GROUP BY x.ID, ISNULL(a.Matching_ID, 0), x.Fields2
without the need of a C1
If I am understanding correctly, the problem is that you are trying to update the CTE table. If you update the table directly you should be fine.
Does this modified version help?
SELECT t.ID
, CASE WHEN (EXISTS (SELECT MATCHING_ID FROM AnotherTable WHERE ID = t.ID)) THEN 1 ELSE 0 END
,t.Field2
,Count(*)
FROM TableX t
GROUP BY ID, Fields2