Match all values in IN clause - sql

here is my data:
T1
P.ID UniqueID Value
1 1 Apple
1 2 Orange
1 3 Grapes
2 4 Peach
2 5 Orange
2 6 Banana
T2 (lookup table)
Value
Apple
Orange
Grapes
Peach
Melon
Berry
I need categorize the data into 2 categories:
if all records of each parent id in T1 have a match in T2, then Type1
if any one of the records in T1 for the parent id does not have a
match in T2, then Type2.
Currently, I am using an IN clause to query T2
select ID from T1 where T1.value in(select value from T2)
But I seem to be getting records that do not have a match in T2 as well using thie logic. how do I differentiate these? In my example above, ID 2 should be Type 2, and ID 1 is Type 1.

You could use this query:
select T1.ID,
case count(*) when count(T2.value)
then 'Type1'
else 'Type2'
end as Type
from T1
left join T2 on T1.value = T2.value
group by T1.ID

If you need two queries anyway:
To get type 2:
select unique p_id from t1 where value not in (select value from t2)
Then save (store) the result in a temp table, or make this into a view. Either way, let's say you call it t3.
To get type 1:
select unique p_id from t1 where p_id not in (select p_id from t3)

You could use a temp result that checks for each row separately if the value exists in the lookup table, and then select the max of these checks for each group. Thereby, if at least one row in a group has no reference (i.e. a Type 2 for this row), then the max for the group is Type 2, too:
select id, max(type)
from
(select id, nvl(t2.value,'Type 2', 'Type 1') as type
from t1 left join t2 on t1.value = t2.value)
group by id

Related

If I left join table2 to table1, how I can I call on the IDs in table1 that don't appear in table2 within a CASE or IF Statement?

I am writing an IF/Case statement that requires me to identify all the Ids from and ID column in Table1 that don't appear in a 2nd table Table2 which is left joined on to Table1 on the ID Column, And based on that IF statement I would like to produce a binary column called Missing with 1s, 0s.
Table1
ID
Region
a
US
b
US
c
Mexico
d
Japan
Table2
ID
Years
a
5
d
10
After joining this is what I have:
ID
Region
Years
a
US
5
b
US
null
c
Mexico
null
d
Japan
10
The final outcome should be:
ID
Region
Years
Missing
a
US
5
0
b
US
null
1
c
Mexico
null
1
d
Japan
10
0
I don't know how to Identify those specific Ids in the IF or CASE statement but the rest of the query I can write. I tried to write
IF(Table1.ID NOT IN Table2.ID, 1, 0) As Missing
but that did not work (some sort of unnest issue)
You may try:
SELECT t1.*, t2.ID IS NULL AS Missing
FROM Table1 t1
LEFT JOIN Table2 t2
ON t2.ID = t1.ID;
Using the IF() function we can try:
SELECT t1.*, IF(t2.ID IS NULL, 1, 0) AS Missing
FROM Table1 t1
LEFT JOIN Table2 t2
ON t2.ID = t1.ID;

How to write BigQuery/SQL query to divide average of a column in one table from column in second/another table

I am looking for SQL query to SELECT ratio of Value1/Value2 from two tables as below..
Table_1:
-------
id Type Count
1. A. 2
2. B. 3
3. A. 1
4. A. 4
5. B. 2
Table_2:
id Type Max
1. A. 10
2. B. 10
where Value1 = SELECT AVG(Count) FROM Table_1 GROUP BY Type
and Value2 = SELECT Max FROM Table_2.
I tried below query
WITH table1 (SELECT AVG(Count) as avg_cnt...),
table2 (SELECT Max as max_val....)
SELECT table1.avg_cnt/table2.max_val
FROM ..
But it did not work.
You can just aggregate and calculate:
select t2.type, avg(t1.count) / t2.max
from table1 t1 join
table2 t2
on t1.type = t2.type
group by t2.type, t2.max;
No subqueries or CTEs are needed.
You can try using join
Select cnt/maxval
from
(
select type,avg(count) cnt
from table1
group by type
)A join table2 on table1.type=table2.type

SQL Subquery Join and Sum

I have Table 1 & 2 with common Column name ID in both.
Table 1 has duplicate entries of rows which I was able to trim using:
SELECT DISTINCT
Table 2 has duplicate numeric entries(dollarspent) for ID's which I needed and was able to sum up:
Table 1 Table 2
------------ ------------------
ID spec ID Dol1 Dol2
54 A 54 1 0
54 A 54 2 1
55 B 55 0 2
56 C 55 3 0
-I need to join these two queries into one so I get a resultant JOIN of Table 1 & Table 2 ON column ID, (a) without duplicates in Table 1 & (b) Summed $ values from Table 2
For eg:
NewTable
----------------------------------------
ID Spec Dol1 Dol2
54 A 3 1
55 B 3 2
Notes : No. of rows in Table 1 and 2 are not the same.
Thanks
Use a derived table to get the distinct values from table1 and simply join to table 2 and use aggregation.
The issue you have is you have a M:M relationship between table1 and table2. You need it to be a 1:M for the summations to be accurate. Thus we derive t1 from table1 by using a select distinct to give us the unique records in the 1:M relationship (assuming specs are same for each ID)
SELECT T1.ID, T1.Spec, Sum(T2.Dol1) as Dol1, sum(T2.Dol2) as Dol2
FROM (SELECT distinct ID, spec
FROM table1) T1
INNER JOIN table2 T2
on t2.ID = T1.ID
GROUP BY T1.ID, T1.Spec
This does assume you only want records that exist in both. Otherwise we may need to use an (LEFT, RIGHT, or FULL) outer join; depending on desired results.
I can't really see your data, but you might want to try:
SELECT DISTINCT ID
FROM TblOne
UNION ALL
SELECT DISTINCT ID, SUM(Dol)
FROM TblTwo
GROUP BY ID
Pre-aggregate table 2 and then join:
select t1.id, t1.spec, t2.dol1, t2.dol2
from (select t2.id, sum(dol1) as dol1, sum(dol2) as dol2
from table2 t2
group by t2.id
) t2 join
(select distinct t1.id, t1.spec
from table1 t1
) t1
on t1.id = t2.id;
For your data examples, you don't need to pre-aggregate table 2. This gives the correct sums -- albeit in multiple rows -- if table1 has multiple specs for a given id.

Querying two tables to filter data using select case

I have two tables
Table 1 looks like this
ID Repeats
-----------
A 1
A 1
A 0
B 2
B 2
C 2
D 1
Table 2 looks like this
ID values
-----------
A 100
B 200
C 100
D 300
Using a view I need a result like this
ID values Repeats
-------------------
A 100 NA
B 200 2
C 100 2
D 300 1
that means, I want unique ID, its values and Repeats. Repeats value should display NA when there are multiple values against single ID and it should display the Repeats value in case there is single value for repeats.
Initially I needed to display the max value of repeats so I tried the following view
ALTER VIEW [dbo].[BookingView1]
AS
SELECT bv.*, bd2.Repeats FROM Table1 bv
JOIN
(
SELECT distinct bd.id, bd.Repeats FROM table2 bd
JOIN
(
SELECT Id, MAX(Repeats) AS MaxRepeatCount
FROM table2
GROUP BY Id
) bd1
ON bd.Id = bd1.Id
AND bd.Repeats = bd1.MaxRepeatCount
) bd2
ON bv.Id = bd2.Id;
and this returns the correct result but when trying to implement the CASE it fails to return unique ID results. Please help!!
One method uses outer apply:
select t2.*, t1.repeats
from table2 t2 outer apply
(select (case when max(repeats) = min(repeats) then max(repeats)
else 'NA'
end) as repeats
from table1 t1
where t1.id = t2.id
) t1;
Two notes:
This assumes that repeats is a string. If it is a number, you need to cast it to a string.
repeats is not null.
For the sake of completeness, I'm including another approach that will work if repeats is NULL. However, Gordon's answer has a much simpler query plan and should be preferred.
Option 1 (Works with NULLs):
SELECT
t1.ID, t2.[Values],
CASE
WHEN COUNT(*) > 1 THEN 'NA'
ELSE CAST(MAX(Repeats) AS VARCHAR(2))
END Repeats
FROM (
SELECT DISTINCT t1.ID, t1.Repeats
FROM #table1 t1
) t1
LEFT OUTER JOIN #table2 t2
ON t1.ID = t2.ID
GROUP BY t1.ID, t2.[Values]
Option 2 (does not contain explicit subqueries, but does not work with NULLs):
SELECT DISTINCT
t1.ID,
t2.[Values],
CASE
WHEN COUNT(t1.Repeats) OVER (PARTITION BY COUNT(DISTINCT t1.Repeats), t1.ID) > 1 THEN 'NA'
ELSE CAST(t1.Repeats AS VARCHAR(2))
END Repeats
FROM #table1 t1
LEFT OUTER JOIN #table2 t2
ON t1.ID = t2.ID
GROUP BY t1.ID, t2.[Values], t1.Repeats
NOTE:
This may not give desired results if table2 has different values for the same ID.

Getting results to display that exist in table 1 but not table 2

I'm new to SQL and am having trouble getting results to display that exist in table 1 but not table 2. I need to display how many times each ID from table 1 has been used in table 2 (including 0 if it has not been used) I can get the ID's that exist in Table 1 to display, but not the ID's that don't exist in Table 2.
I am getting:
ID Count
1
1
1
1
1
1
2
but need:
ID Count
1
1
1
0
1
1
0
1
2
I have tried:
SELECT COUNT (PID) AS [ID Count]
FROM SalesOrderProduct
WHERE PID > = 0
GROUP BY PID;
(just for this column that i can't get the 0 values to display in)
Table 1: PID, Description
Table 2: PID, Status
How can I get the results to display showing all the counts for ID in Table 2, including when the count is 0 using UNION?
Thanks everyone
Try this, you can change the attribute name based on your table structure.
Select t1.id, count(t2.id)
From t1 left join t2
on (t1.id = t2.id)
Group By t1.id;
in this case that your ids are not unique use exists with a count plus a union like:
select distinct tbl.id, 0 cnt --for ids not exists in table2
from table1 tbl
where not exists (select t.id from table2 t where t.id=tbl.id)
union
select t1.id, count(t1.id) cnt ----for ids exists in table2
from table1 t1
where exists (select t2.id from table2 t2 where t1.id=t2.id)
group by t1.id