Exclude rows that return NULL for a column when using a Case statement - tsql

SELECT ir.objectid,ir.objecttype,ir.name,ir.email,ir.createdate,
CASE objecttype
WHEN 1 THEN (select friendlyurl
from locations
where id = ir.objectid)
END as objecturl
FROM inforequests ir
WHERE createdate > '1/1/2014'
order by CreateDate asc
This query returns 10 rows for me, but 1 row shows NULL for column objecturl, which happens if no record is found in the [locations] table.
How can I alter my query to make sure that when objecturl IS NULL, that row is not returned, so in my case my query would only return 9 rows.

Add it to the WHERE clause:
where createdate > '1/1/2014' and objecttype = 1
Since your CASE does not handle any other values, it will result in a NULL when objecttype <> 1.
Alternatively, you could nest SELECTs:
select *
from ( SELECT ir.objectid,ir.objecttype,ir.name,ir.email,ir.createdate,
CASE objecttype
WHEN 1 THEN (select friendlyurl
from locations
where id = ir.objectid)
END as objecturl
FROM inforequests ir
WHERE createdate > '1/1/2014' ) as Temp
where objecturl is not NULL
order by CreateDate asc
Note that this is somewhat different as it will also exclude rows for which the correlated subquery returns NULL.

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

Can lead() return the next row only when a condition is met?

Recently my company upgraded from SQL Server 2008 to 2016, so I want to take advantage of some "new" features, one of which is lead().
I understand the basic usage, but I want to know if I can return the next row only when a condition is met. My original query looked like the following, where x.next_id is null if the next row isn't more than 12 days past the current row.
SELECT
a.id,
a.date_a,
x.next_id
FROM
table a
OUTER APPLY
(SELECT TOP 1
next_id = i.intIndex
FROM
table i
WHERE
i.date_a > DATEADD(DAY, 12, a.date_a)
ORDER BY
date_a, id ASC) x
ORDER BY
date_a, id ASC
Data might look like the following, where the third column is added by the query:
id date_a next_id
--------------------------------
1798678 2014-12-01 NULL
1798689 2013-01-05 1798688
1798688 2014-03-31 NULL
1798696 2013-04-03 1798694
1798694 2013-08-12 1798691
1798691 2014-09-30 NULL
1798698 2013-05-14 1798697
1798697 2013-08-29 NULL
Assuming this data set (your result table; minus the result column):
CREATE TABLE some_table(id INT PRIMARY KEY,date_a DATE);
INSERT INTO some_table(id,date_a)
VALUES (1798678,'2014-12-01'),
(1798689,'2013-01-05'),
(1798688,'2014-03-31'),
(1798696,'2013-04-03'),
(1798694,'2013-08-12'),
(1798691,'2014-09-30'),
(1798698,'2013-05-14'),
(1798697,'2013-08-29');
This query returns the same result set as what the query you have returns:
SELECT
id,
date_a,
next_id=
CASE WHEN LEAD(date_a) OVER (ORDER BY date_a,id)>DATEADD(DAY,12,date_a)
THEN LEAD(id) OVER (ORDER BY date_a,id)
ELSE NULL
END
FROM
some_table
ORDER BY
date_a,id;

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

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