Different where clause columns based on group by count of joined table - mysql

Given the following 2 tables
table_a
id name num_one num_two
------------------------------------
1 Foo 5 10
2 Bar 4 -1
table_b
name table_a_id
--------------------
Fooa 1
Foob 1
Suppose I want to use ether num_one or num_two in a where clause depending on if another table has joined rows or not.
The best thing I can come up with is this:
SELECT a.* FROM table_a a
JOIN table_b b on b.table_a_id = a.id
WHERE if(count(b.*) > 0, a.num_one, a.num_two) > 0
group by a.id
Ideally it would check if 5 > 0 on the first row and -1 > 0 on the 2nd because the 2nd row as no joined rows from table B.
But it errors with invalid use of group by. I know about "having" but not sure how I could use it in this situation.
Any ideas? Thanks!!

This can be done with an IF statement, OR statement or a subquery. None of which will be very efficient on a large table.
The only real modification to your original statement was the use of NULL instead of count(*).
SELECT DISTINCT a.*
FROM table_a a
LEFT JOIN table_b b on b.table_a_id = a.id
WHERE (b.table_a_id is null AND a.num_one > 0)
OR (b.table_a_id is NOT NULL AND a.num_two > 0)

Related

To show the aggregate of duplicated values that another corresponding attribute in another table is NOT NULL

Not sure if I have described the context clearly in the title
but the situation is given two tables
A|B
1|1
1|2
2|3
2|4
3|5
4|6
5|7
5|8
B|C
1|NULL
2|1
3|NULL
4|NULL
5|NULL
6|2
7|3
8|4
the condition of output is the value of A should appear more than 1 time,
while the corresponding B values are not both NULL in C (at least 1 value of C from B is not NULL)
what matches the conditions of the above table by A should be 1 and 5
the expected output of the count of duplicated A is 2
The following should help.
select t.a,count(t.a),count(t2.c)
from t
join t2
on t.b=t2.b
group by t.a
having count(t.a)>1
and count(t2.c)>=1
Here i join the table t and t2 on the column b
after that i check how many records have col-a in table t are >1 and also how many in col c in t2 are> 1.
Just FYI,count(null) would be zero) so any non-null value in t2.c will have count(t2.c)>=1
Full demo
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=6d56b0ed8bafe09786342a6bfb58b8d2
you can try by using exists
select t1.A,count(*) as duplicate
from tableA t1
where exists ( select 1 from tableB t2 where t2.B=t1.B
and COALESCE(t2.B,t2.c) is not null
)
group by t1.A
having count(*)>1

Check if table a primary key is exist in table b

Table A:
ID, Name, etc.
Table B:
ID, TableA-ID.
SELECT * FROM A;
and I want to return a boolean value in the same result for this condition ( if A.ID Exists in Table B).
There are several ways of achieving what you need. Below are three possibilities. These all differ in execution plans and how database actually wants to execute them so depending on your record count one may be more efficient than the other. It's better if you see it for yourself.
1) Use LEFT JOIN and check if a non-null field from B is not null to ensure the record exists. Then apply DISTINCT clause if relationship is 1:N to only show rows from A without duplicates.
select distinct a.*, b.id is not null as exists_b
from a
left join b on
a.id = b.tablea-id
2) Use exists() function, which will be evaluated for each row being returned from table A.
select a.*, exists(select 1 from b where a.id = b.tablea-id) as exists_b
from a
3) Use a combination of subquery expression EXISTS and it's contradiction in two queries to check if a record has or has not a match within table B. Then UNION ALL to combine both results into one.
select *, true as exists_b
from a
where exists (
select 1
from b
where a.id = b.tablea-id
)
union all
select *, false as exists_b
from a
where not exists (
select 1
from b
where a.id = b.tablea-id
)
select A.*, IFNULL((select 1 from B where B.TableA-ID = A.ID limit 1),0) as `exists` from A;
The above statement will result in a 1, if the key exists, and a 0 if that key does not exist. Limit 1 is important if there are multiple records in B

SQL: how to select customers who have ordered multiple items

here is some sample data:
ID Item
1 A
1 A
1 B
2 A
2 A
3 A
3 A
3 A
Question: Im trying to write code so that the only records that are selected are those of customer with ID 1 (ie a customer that has both product A and B). So results should look like this:
1 A
1 A
1 B
I've tried a lot of different things, but I am stuck. I tried self-join, but it doesnt produce what I want:
SELECT a.id, a.item
FROM table1 a Join table1 b on a.id=b.id
WHERE upper(a.item) = 'A'
AND upper(b.item) = 'B';
This will give me the right customer (ie customer 1) but it doesnt pull all 3 records. It just gives 1 row.
the closest similar question is
enter link description here
since you want to see which users match a certain condition and the fetch everything about those users - you need a nested query:
SELECT id,item FROM table1 WHERE id IN(
SELECT a.id
FROM table1 a Join table1 b on a.id=b.id
WHERE upper(a.item) = 'A'
AND upper(b.item) = 'B'
)
I took your working query, and used it in a WHERE clause for a more generic query - should do the trick for you
You could use your query as subselect to get the pid and then output all the pids rows. Like this:
SELECT id, item
FROM table1
WHERE id IN (SELECT a.id
FROM table1 a
JOIN table1 b
ON a.id=b.id
WHERE UPPER(a.item) = 'A'
AND UPPER(b.item) = 'B')
is it this what you are looking for? or may be I didn't understand your question.
SELECT a.pid, a.mname
FROM meds a
WHERE a.pid = 1

How to perform LEFT OUTER JOIN in hive without duplicates to check only one value in the right table?

I have two datasets:
1)
Table A
id name
1 raju
2 ramu
2 ramu
3 rakesh
Table A
2)
Table B
id Status
1 Y
1 Y
2 N
2 N
2 Y
3 N
Table B
I want to perform a left outer join (Table A Left outer join Table B) in hive in such a way that while joining the two datasets on column 'id', if the Status column in table B has 'Y' at least once, then the resultant dataset will have the Status as 'Yes' like below:
Final Result:
id name Status
1 raju Yes
2 ramu Yes
2 ramu Yes
3 rakesh No
I do not want to increase the number of records in the result while performing the join. The result table should have only 4 records, not 5(increased
records based on the matching join condition).
How do I achieve this?
To meet this requirement, you need to reduce the row count of your table B to either one row or zero rows per row of table A.
Do that like this, getting one row for every id value with a status of Y.
SELECT DISTINCT id, Status
FROM B
WHERE Status = 'Y'
Then you can use the old LEFT JOIN ... IS NOT NULL trick to figure out which rows of A have matching rows of B.
This does it. (http://sqlfiddle.com/#!9/71d84b/1/0)
SELECT A.id, A.name,
CASE WHEN B.Status IS NOT NULL THEN 'Yes' ELSE 'No' END Status
FROM A
LEFT JOIN (
SELECT DISTINCT id, Status
FROM B
WHERE Status = 'Y'
) B ON A.id = B.id

Subtract rows from a table, using subquery which may be empty

table: A
-----------
value
1
2
3
sub-query: B
-----------
value
2
I need (A - B).
The below query works when B is not empty. Output = (1,3) as expected.
SELECT * FROM A
JOIN B
ON (A.value != B.value)
However, when the sub-query B is empty, the JOIN does an intersection of A with an empty B, and the output is an empty result-set.
And if I use LEFT JOIN, it does not subtract the row containing value 2 from table A.
Is it possible to write a single query for (A - B), irrespective of whether B is empty or not.
SELECT A.*
FROM A
LEFT JOIN B
ON A.value = B.value
WHERE b.value IS NULL