Select cases from long table by key variable grouping - sql

I have a table like below:
caseid | ncode | code | test
1 1 ABC TRUE
1 2 DEF TRUE
2 1 ABC TRUE
3 1 DEF TRUE
3 2 HIJ FALSE
Where caseid represents an individual case. This table creates the relationship that each individual case can have multiple codes associated with it (ncode and code). test is just a variable that tracks a boolean value of interest.
I have specific requirements for my query:
I need all cases where code = ABC and ncode = 1 and test = TRUE. This criteria has the highest priority.
Of those cases from #1, I need to create an additional column called hasdef that is a boolean that indicates if that specific caseid has any other rows where code = DEF and test = TRUE. It should be TRUE if so, otherwise FALSE.
So from the above table, what should return is:
caseid | ncode | code | test | hasdef
1 1 ABC TRUE TRUE
2 1 ABC TRUE FALSE
caseid = 1 returns because code = ABC, ncode = 1, and test = TRUE. hasdef = TRUE because in the second row, caseid = 1, code = DEF and test = TRUE.
caseid = 2 returns because code = ABC, ncode = 1, and test = TRUE. hasdef = FALSE because there is no other row with caseid = 2 where code = DEF.
caseid = 3 does not return. Even though there is a row where code = DEF and test = TRUE, the first criteria (code = ABC and ncode = 1) is not first satisfied.
This is what I have so far, but I am not confident it is working as desired:
select tab1.*, tab2.code is not null as hasdef from
(select * from mytable
where code = 'ABC' and ncode = 1) as tab1
left join (
select caseid, any_value(code) code, any_value(test) test
from mytable
group by caseid
having code = 'DEF' and test is true
) as tab2
using(caseid)
order by caseid

Below is for BigQuery Standard SQL
#standardSQL
select * from (
select *,
0 < countif(code = 'DEF' and test is true) over(partition by caseid) as hasdef
from `project.dataset.table`
)
where code = 'ABC' and ncode = 1 and test is true
if to apply to sample data from your question - output is
Note: you can replace test is true with just test as in below
select * from (
select *,
0 < countif(code = 'DEF' and test) over(partition by caseid) as hasdef
from `project.dataset.table`
)
where code = 'ABC' and ncode = 1 and test

Related

Select rows from related table which matches different conditions

I have a table called places which looks like this:
and another table called place_addons_saved which looks like this:
How can I write a query that relates place_addons_saved.place and places.id and searches rows that matches ONLY places which have all the conditions?
For example when I'll search for rows that have place_addon = 163, place_option = 329 and place_addon = 162, place_option = 324 will return place with id of a 80, but when I'll search for rows that have place_addon = 162, place_option = 326 and place_addon = 163, place_option = 330 the query must return nothing, because place 80 doesn't fit the 2nd condition
If I understand correctly, you can use group by and having:
select place
from place_addons_saved
where (place_addon = 163 and place_option = 329) or
(place_addon = 162 and place_option = 324)
group by place
having count(*) = 2; -- "2" is the number of comparisons
To get all the information about the places:
select p.*
from places p
where p.id in (select place
from place_addons_saved
where (place_addon = 163 and place_option = 329) or
(place_addon = 162 and place_option = 324)
group by place
having count(*) = 2; -- "2" is the number of comparisons
);
This could work:
With GetResult (place,chk1,chk2) As
(
SELECT
pas.place,
sum(Case When (pas.place_addon = 163) AND (pas.place_option = 329) then 1 Else 0 End) As chk1,
sum(Case When (pas.place_addon = 162) AND (pas.place_option = 324) then 1 Else 0 End) As chk2
FROM
places AS p RIGHT OUTER JOIN
place_addons_saved AS pas ON p.id = pas.place
group by pas.place
)
Select * From GetResult Where chk1 > 0 and chk2 > 0

sql how to add inner join and multiple conditions to filter

I have this query
SELECT DISTINCT IP.IRId
FROM cmp.NPTable NP
INNER JOIN IPTable IP ON IP.IPtId = NP.IPd
LEFT JOIN IPCTable IPC ON IPC.IPId = NP.IPId
WHERE NP.PCN Id = #PCNId
AND (IP.IsCompliant = 1 AND IPC.CheckId = 1) OR (IP.IsCompliant = 0 AND IPC.CheckId = 1)
This is not working correcty
THe IPTable either has IsCompliant = null, 0 or 1 -- this is basically to indicate true or false
IPC.CheckId is either 1 or 2 -- this is the primary ID in this table
The only match integer match is the value 1 between the two tables.
I only want to bring back rows if IsCompliant = 1 and CheckId = 1
else if IsCompliant is null or 0, then CheckId = 2.
The clause I added to my where which is
AND (IP.IsCompliant = 1 AND IPC.CheckId = 1) OR (IP.IsCompliant = 0 AND IPC.CheckId = 1)
This does not work. Help. Will be very appreciated.
Thanks
WHERE NP.PCN Id = #PCNId
AND
(
(IP.IsCompliant = 1 AND IPC.CheckId = 1) OR
((IP.IsCompliant is null or IP.IsCompliant = 0) AND IPC.CheckId = 2)
)

IF Column has a value

I need to write sql query to check whether the column y in a table x has a value. In python I can check that like
object.y = 1
if object.y:
<statements>
Like this I need to check in Postgres
this is my query:
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and y is TRUE order by sequence""",([event_root]))
Here I need to check y has a value.
try this
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and coalesce(y, FALSE) is TRUE order by sequence""",([event_root]))
This is my solved answer
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang is NULL and y is not null order by sequence""",([event_root]))
reference: https://www.techonthenet.com/postgresql/is_not_null.php

SQL: Variable to update a set of items

SO, each item has an id, a setId, and a name.
Current data may only have one NAME field filled out in an entire set.
EX>
>ID = 1 >NAME = 'Bob' >SETID = 5
>ID = 2 >NAME = NULL >SETID = 5
>ID = 3 >NAME = NULL >SETID = 5
>ID = 4 >NAME = NULL >SETID = 5
I am looking for an SQL script that GET the one record that is not null in a "SET"
SET the remaining items in the "SET" for that "NAME" record.
The end result I am aiming for would look like this:
>ID = 1 >NAME = 'Bob' >SETID = 5
>ID = 2 >NAME = 'Bob' >SETID = 5
>ID = 3 >NAME = 'Bob' >SETID = 5
>ID = 4 >NAME = 'Bob' >SETID = 5
Assuming there is only one Name in a set that is not null, you could use a CTE and do something like:
;WITH NameHelper AS
(
SELECT
Name,
SetID
FROM MyTable
WHERE Name IS NOT NULL
GROUP BY Name, SetID
)
UPDATE MyTable SET Name = NameHelper.Name
FROM MyTable
INNER JOIN NameHelper ON MyTable.SetID = NameHelper.SetID

Understanding case expression in the "Where" clause

I've got this code here and you can see from my Pseudocode what I'm trying to accomplish
select *
from dbo.BenefitsForms
inner join Dependents on BenefitsForms.UserId = Dependents.BenefitsForm_UserId
inner join CoverageLevels on BenefitsForms.MedicalId = CoverageLevels.Id
where (BenefitsForms.MedicalId > 0 AND BenefitsForms.MedicalId < 13)
AND Dependents.IsSpouse = CASE when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0 end
when CoverageLevels.[Level] = 4 then [any, it doesnt matter] <--- my desire but it doesn't work.
What can I do to get the effect I desire in the brackets? If Coverage Level = 4 then I don't care what Dependents.IsSpouse is, I don't even need to sort by it anymore.
Assuming that isSpouse can only be 0 or 1... if CoverageLevels.Level is 4, then compare isSpouse to itself, which will always result in true:
AND Dependents.IsSpouse = CASE
when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0
when CoverageLevels.[Level] = 4 then Dependents.IsSpouse
END
Alternately, this can also be expressed without the CASE:
WHERE
BenefitsForms.MedicalId > 0
AND BenefitsForms.MedicalId < 13
AND (
(Dependents.IsSpouse = 1 AND CoverageLevels.[Level] = 2)
OR (Dependents.IsSpouse = 0 AND CoverageLevels.[Level] = 3)
OR CoverageLevels.[Level] = 4
)