Filter rows based on multiple condition in where statement in PostgreSQL - sql

I have following table in Postgres 11.0
id status
NCT00632827 true
NCT00632827 (null)
NCT00770185 false
NCT00770185 (null)
NCT00784303 (null)
NCT00784303 (null)
The id values are duplicated due to different value in status column. I would like to keep the rows with either true or false. If multiple rows have null value, I would like to keep only 1 row. The desired output is:
id status
NCT00632827 true
NCT00770185 false
NCT00784303 (null)
I am trying following query:
select id, status
where status = 'false' or status = 'true'
from table
How can I keep rows with null value (last row in the desired output)?

For this dataset, simple aggregation seems good enough to produce the expected results:
select id, bool_or(status) status from mytable group by id

Related

need to pull a specific record

There is 1 record having duplicate values except in 1 column having x and y
record status
XXXXXXXXXX A
XXXXXXXXXX B
Need to pull A only and remove the other duplicate B
Select record
case
when status in ("'a', 'b'") then ('a')
from xyz
Let suppose you have data as below where Status is repeating for First column
but you are interesting in the status which is of having lower value as given below:
In this case following SQL may help. Here, we are partitioning on key field and ordering the Status so that we can apply filter on rank to get desired result.
WITH sampleData AS
 (SELECT '1234' as Field1,  'A' as STATUS UNION ALL 
  SELECT '1234',  'C' UNION ALL
  SELECT '5678', 'A' UNION ALL 
  SELECT '5678',  'B' )
 select * except(rank) from (
 select *, rank() over (partition by Field1 order by STATUS ASC) rank from sampleData)
 where rank = 1
 order by Field1
Consider below approach
select * from sampledata
qualify 1 = row_number() over win
window win as (partition by field1 order by if(status='A',1,2) )
if applied to sample data in your question - output is

How to summarize table based on other column values?

There is a decision table as follows:
Id decision
1 NULL
1 NULL
1 yes
1 NULL
2 no
2 no
2 no
3 yes
3 no
3 yes
The result should return :
Id decision
1 Decision Pending
2 no
3 yes
So for each Id in the decision table:
If any of the decision value is NULL then it is to be set to
"decision pending". eg. id 1
If there is no NULL and any of the decision is yes then final
decision is set to be "yes". eg. id 3
If there is no NULL and all the decisions are no then final decision
is set to be as "no". eg. id 2
What should the azure sql query to get the above mentioned result?
P.S. I am new to SQL, so having trouble figuring this out.
SELECT
id,
CASE
WHEN COUNT(*) > COUNT(decision)
THEN 'pending'
ELSE MAX(decision)
END
AS decision
FROM
decision
GROUP BY
id
GROUP BY id ensures that you get one row per id.
COUNT(*) tells you how many rows there are for that id.
COUNT(decision) tell you how many of those rows have NOT NULL decisions.
COUNT(*) > COUNT(decision) is therfore TRUE if any of the decisions in the group are NULL.
MAX(decision) returns yes if there are any yes values in the group, and no only if there aren't any yes values in the group.
One way is to compare the count(*) and count(decision) which reveals if a row is null and use an inline if to succinctly know to use the aggregate
select id, Iif(Count(*)=Count(decision),Max(decision),'Decision Pending')
from Decision
group by id

NULL behavior with Comoperator like ALL in Oracle SQL

SELECT * FROM hr.NullValueCheck
ID Name
1 abc
2 abc
3 bcd
4 cde
https://oracle-base.com/articles/misc/all-any-some-comparison-conditions-in-sql
Query 1 :
SELECT *
FROM hr.NullValueCheck
where id > All (SELECT NULL FROM DUAL )
Nothing is coming.
But for below quesry. All records are coming while subquesry is returning is NULL same as like above query (SELECT NULL FROM DUAL )
Query 2:
SELECT *
FROM hr.NullValueCheck
where id > All (SELECT id from hr.NullValueCheck where id = 5)
Please explain me why Query 1 is returning No Records but Query 2 is returning all records.
As per my knowledge Query 1 should also return all records.
NULL is different from an empty set.
The first example is saying: "select all rows where the id is greater than all values of NULL". Or more simply, "where id is greater than 'NULL'`.
In SQL, 'NULL' generally has the semantics of "not known". If you don't know the value, then you don't know if a given id is larger. Hence, no rows are returned.
In the second example, instead has an empty set for comparison. An empty set is not NULL. Obviously, any number is greater than all numbers in an empty set. Hence, all rows are returned.

Find certain values and show corresponding value from different field in SQL

So I found these 2 articles but they don't quite answer my question...
Find max value and show corresponding value from different field in SQL server
Find max value and show corresponding value from different field in MS Access
I have a table like this...
ID Type Date
1 Initial 1/5/15
1 Periodic 3/5/15
2 Initial 2/5/15
3 Initial 1/10/15
3 Periodic 3/6/15
4
5 Initial 3/8/15
I need to get all of the ID numbers that are "Periodic" or NULL and corresponding date. So I want a to get query results that looks like this...
ID Type Date
1 Periodic 3/5/15
3 Periodic 3/6/15
4
I've tried
select id, type, date1
from Table1 as t
where type in (select type
from Table1 as t2
where ((t2.type) Is Null) or "" or ("periodic"));
But this doesn't work... From what I've read about NULL you can't compare null values...
Why in SQL NULL can't match with NULL?
So I tried
SELECT id, type, date1
FROM Table1 AS t
WHERE type in (select type
from Table1 as t2
where ((t.Type)<>"Initial"));
But this doesn't give me the ID of 4...
Any suggestions?
Unless I'm missing something, you just want:
select id, type, date1
from Table1 as t
where (t.type Is Null) or (t.type = "") or (t.type = "periodic");
The or applies to boolean expressions, not to values being compared.

Modifying column value according to status, and adding extra rows. (sql)

In my table I have a "name" column and a "status" column.
the status is either true or false.
And another table contains a number which is a total amount.
The result that I want to get is a table with two columns:
name | status
and and example of a data:
a | available
a | available
a | not available
a | not available
a | available
when "a" is in the name column and the availability is the status column.
The total amount from the second table indicates the total number of "a" rows that i need to have, and the status depends on the true/false from the status column in the original table.
If the status is "true" I need to write "available" and when "false" then "not available".
If the total amount value is bigger than the data I have in the first table, I need to add rows according to the total amount with the status "available".
For example, If I have 3 records of "a", when one has the status "true" and the other two have the status "false", and the total amount is 4, In the result I need to get 4 rows with the name "a", 2 of them "available" and 2 "not available" (the given 3 rows, plus one row to make it 4).
My question is, how can I change the value according to the data in the table? (Write available/ not available)
And how can I add a certain amount of rows with preset values (same name as before, and "available" status)?
"...how can I change the value according to the data in the table?"
You can use CASE() to test for the value of the column.
SELECT name,
CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available'
END status
FROM tableName
For future answer-seekers:
To get the 'fake' rows, one way is to use are recursive CTE:
WITH Expanded_Data as (SELECT Counted_Data.name,
CAST('true' as VARCHAR(5)) as status,
Counted_Data.count + 1 as count,
Total.count as limit
FROM (SELECT name, COUNT(*) as count
FROM Data
GROUP BY name) Counted_Data
JOIN Total
ON Counted_Data.name = Total.name
AND Counted_Data.count < Total.count
UNION ALL
SELECT name, status, count + 1, limit
FROM Expanded_Data
WHERE count < limit)
SELECT name, CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available' END
FROM (SELECT name, status
FROM Data
UNION ALL
SELECT name, status
FROM Expanded_Data) d;
(have a working SQL Fiddle example.)
I'm a little worried about the initial duplication in the source data though; I can only hope there is more 'unique' information as well.