One query that matches values with only one condition out of two, one query that matches values with both conditions - sql

I'm having some sort of a blank about how to do this in SQL.
Consider this reprex in R
set.seed(123)
data.frame(ID = (sample(c(1:5), 10, replace = T)),
status = (sample(c("yes", "no"), 10, replace = T)),
amount = (sample(seq(1,50,0.01),10)))
which gives out this table
ID status amount
1 3 no 29.87
2 3 yes 26.66
3 2 yes 15.49
4 2 yes 18.89
5 3 yes 44.06
6 5 no 30.79
7 4 yes 17.13
8 1 yes 6.54
9 2 yes 45.68
10 3 yes 12.66
I need to find two SQL queries.
One where I select the ID's that only have status of 'NO'
meaning ID 5.
and
One where I select the ID's that match both conditions, meaning ID 3
I have a query for both but I'm almost sure it's not correct so any lead is more than welcome.
Thanks

One where I select the ID's that only have status of 'NO' meaning ID 5.
select id from your_table where status='no' and id not in (select id from
your_table where status='yes')
One where I select the ID's that match both conditions, meaning ID 3
select id from your_table where status='no' and id in (select id from
your_table where status='yes')
At last I think you are expecting ids which do not match these conditions. so UNION both queries and get ids of your table which not exists after UNION
select id from your_table where id not in (
select id from your_table where status='no' and id not in
(select id from your_table where status='yes')
union all
select id from your_table where status='no' and id in
(select id from your_table where status='yes')
)

Related

How to replace subquery with in statement in bigquery

I happen to stumble with a problem using bigquery, I have to build a query where I need to limit the number of ids within the left join to a subset of a query, unfortunately bigquery does not support subquery.
I've been trying to find a solution that will allow me to place this constraint within the join but haven't been successful usually the solution I encounter suggest the usage of crossjoin but I haven't had success with it so far, here is in a nutshell the table structure I have and the query I'm trying to construct:
#standardSQL
WITH User AS (
SELECT 1 AS id, "A" AS items UNION ALL
SELECT 2 AS id, "B" AS items UNION ALL
SELECT 3 AS id, "c" AS items),
Label_User AS (
SELECT 1 AS user_id, 1 AS label_id UNION ALL
SELECT 1 AS user_id, 4 AS label_id UNION ALL
SELECT 1 AS user_id, 3 AS label_id UNION ALL
SELECT 2 AS user_id, 1 AS label_id UNION ALL
SELECT 2 AS user_id, 2 AS label_id),
Labels AS (
SELECT 1 AS id, "Test" AS label UNION ALL
SELECT 2 AS id, "Admin" AS label UNION ALL
SELECT 3 AS id, "Local" AS label UNION ALL
SELECT 4 AS id, "External" AS label)
select * from User left join Label_User on id=user_id and
label_id in (select id from Labels where label = "External" or label ="Local")
-- This works for a single record of label id
-- select * from User left join Label_User on id=user_id and label_id = 1
Any help would be very appreciated.
Edit 1
Thanks #mikhail-berlyant for his suggestion, but the issue I've found with having the condition in the where clause, it's that it filters out some records that I need, so the result I'm looking for looks like this:
id items user_id label_id
1 A 1 4
1 A 1 3
2 B null null
3 C null null
But having the filter in the where output this:
Row id items user_id label_id
1 A 1 4
1 A 1 3
Below is for BigQuery Standard SQL
#standardSQL
SELECT *
FROM User
LEFT JOIN (
SELECT *
FROM User
LEFT JOIN Label_User
ON id = user_id
WHERE label_id IN (SELECT id FROM Labels WHERE label = "External" OR label ="Local")
)
USING (id, items)
when applied t sample data from your question - output as below
Row id items user_id label_id
1 1 A 1 4
2 1 A 1 3
3 2 B null null
4 3 C null null

Database Peer to peer relationship

I have a table case which has case Id case Name
caseId | CaseName
------ |---------
1 | Case 1
-------|-------
2 |Case2
-------|-------
3 |Case 3
-------|-------
4 |Case 4
I have a requirement where all these cases are related, something like this:-
1-2
1-3
1-4
2-3
2-4
3-4
How to store the records in an efficient way
Make another table. Case Id and Related Case Id columns should have same data type as Case Id in your first table.
Case Id Related Case Id
1 4
2 4
2 3
Since it is a many to many relation, you can create a junction table with both columns as a foreign key to case.
case_relation (case_id_1, case_id_2). Something like this.
If caseId column have unique values
with t( caseId )as (
select 1 from dual union all
select 2 from dual union all
select 3 from dual union all
select 4 from dual
)
select t1.caseId, t2.caseId from t t1
cross join t t2
where
t1.caseId < t2.caseId

Select unique subsets

I have a table like in example below.
SQL> select * from test;
ID PARENT_ID NAME
1 1 A
2 1 B
3 2 A
4 2 B
5 3 A
6 3 B
7 3 C
8 4 A
What I need is to get all unique subsets of names ((A,B), (A,B,C), (A)) or exclude duplicate subsets. You can see that (A,B) is twice there, one for PARENT_ID=1 and one for 2.
I want to exclude such duplicates:
ID PARENT_ID NAME
1 1 A
2 1 B
5 3 A
6 3 B
7 3 C
8 4 A
You can use DISTINCT to only return different values.
e.g.
SELECT DISTINCT GROUP_CONCAT(NAME SEPARATOR ',') as subsets
FROM TABLE_1
GROUP BY PARENT_ID;
SQL Fiddle
I have used 'group_concat' assuming you are using 'Mysql'. The equivalent function in Oracle is 'listagg()'. you can see it in action here in SQL fiddle
Here is the solution:-
Select a.* from
test a
inner join
(
Select nm, min(parent_id) as p_id
from
(
Select Parent_id, group_concat(NAME) as nm
from test
group by Parent_ID
) a
group by nm
)b
on a.Parent_id=b.p_id
order by parent_id, name

SQL select Name entries for which a certain requirement is NEVER fulfilled

I need to select Name entries for which none of the rows fulfills a certain requirement. This is best described as an example- lets consider the following table:
Name Number ID
A 1 2
A 2 2
B 1 2
B 2 3
C 3 3
The requirement would be that Number=ID. For the name B this is never the case, so I would like to return the Name B.
Name Number ID
A 1 2
A 2 2 <---- fulfills requirement for A
B 1 2
B 2 3
C 3 3 <---- fulfills requirement for C
Is this possible in SQL?
You can use a NOT EXISTS clause
select * from Table1 t1
where not exists (select null
from Table1
where t1.Name = Name
and Number = Id)
If you just want the names which don't fulfill the requirement, just change the select to
select distinct t1.Name
see SqlFiddle with both versions.
Try this
Select Name
from table
where name not in (Select distinct name from table where number = id )

Active Record select 15 records order by date with different field value using

Here I have some articles:
id text group_id source_id
1 t1 1 1
2 t2 1 1
3 t3 2 2
4 t4 3 4
So I want to have records in result ordered by created_at column (it exists, but I didn't show it in table) and having distinct group id, such as that:
id text group_id source_id
1 t1 1 1
3 t3 2 2
4 t4 3 4
Also, I should be able to filter result with source_id.
I'm stuck with this question for two days and don't even know how to start solve problem.
Assuming you want the minimum values of the non-duplicated columns, try:
select min(id) as id,
min(text) as text,
group_id,
source_id,
min(created_at) as created_at
from articles
where source_id = #your_parameter_value
group by group_id,
source_id
order by 5
Select * from
(Select * from articles
Order by group_id, id) x
Group by group_id