I have transaction table with columns transaction_id, transaction_category and transaction_quantity. Please view the sample data below
transaction_id | transaction_category | transaction_quantity |
---|---|---|
112 | sale | 1000 |
112 | internal | 1000 |
113 | sale | 1000 |
114 | sale | 1000 |
114 | internal | 1000 |
115 | sale | 1000 |
115 | external | 1000 |
116 | sale | 1000 |
116 | internal | 1000 |
In the given table, notice transaction_id 112 has both 'sale' and corresponding row with same transaction_id and 'internal' category. It is the same with transaction_id 114. But the third row with transaction_id 113 does not have another row with 'internal' category and transaction_id 115 also doesn't have a corresponding row with 'internal' category (it has external).
I need to get the list of all transactions that have transaction_category of 'sale' but does not have a corresponding transaction_category of 'internal'. So it should return rows with transaction_id of 113 and 115 in the above case. I was attempting to do this with the minus operator but have been hitting a brick wall attempting to do this.
EDIT: The table is about 5000 rows and none of the columns are indexed. Also, there are other categories too. I will update my table.
CodePudding user response:
You may try with conditional aggregation as the following:
select transaction_id
from table_name
group by transaction_id
having count(case when transaction_category='sale' then 1 end) > 0 and
count(case when transaction_category='internal' then 1 end) = 0
See a demo.
CodePudding user response:
SELECT T.TRANSACTION_ID
FROM TRANSACTIONS AS T
WHERE T.transaction_category='SALE'
EXCEPT --MINUS
SELECT T.TRANSACTION_ID
FROM TRANSACTIONS AS T
WHERE T.transaction_category='INTERNAL'
May be this one
CodePudding user response:
Solution for MySQL 8.0.31, which now supports EXCEPT
.
select distinct transaction_id from transaction where transaction_category = 'sale'
except
select transaction_id from transaction where transaction_category = 'internal';
MINUS
is a synonym invented by Oracle and supported for compatibility in some other SQL implementations (but not MySQL).
I put the distinct
in that query because it's not clear from your description if there can be only one row per category for a given transaction_id.
See also:
- https://blogs.oracle.com/mysql/post/intersect-and-except-in-mysql-80
- https://dev.mysql.com/doc/refman/8.0/en/set-operations.html
CodePudding user response:
Like already mentioned in other answers, EXCEPT
is absolutely fine.
Another good option is EXISTS
:
SELECT
transaction_id
FROM transactions t1
WHERE transaction_category = 'sale'
AND NOT EXISTS
(SELECT 1 FROM transactions t2
WHERE t1.transaction_id = t2.transaction_id
AND t2.transaction_category = 'internal');
I guess it should be clear we will add a DISTINCT
if we only want to get every transaction id once.