Select rows not in another table by comparing two table - sql

I have following two tables TableA and TableB
TableA
Id Month_Id Customer_Id Total_Amount
1 1 1 50
2 2 1 150
3 3 1 200
4 1 2 75
5 2 2 100
6 1 3 400
7 2 3 200
TableB
Id Month_Id Customer_Id Total_Amount
1 1 1 50
2 2 1 150
3 1 2 75
I want to compare Month_Id Customer_Id Total_Amount in both tables and select Id from TableA. The output should be as follow.
Output
Id
3
5
6
7
My concept is:
SELECT TableA.Id FROM TableA
WHERE TableA.Month_Id <> TableB.MonthId AND
TableA.Customer_Id <> TableB.Customer_Id AND
TableA.Total_Amount <> TableB.Total_Amount

SELECT TableA.Id
FROM TableA
WHERE NOT EXISTS (
SELECT 1
FROM TableB
WHERE TableB.Month_Id = TableA.Month_Id
AND TableB.Customer_Id = TableA.Customer_Id
AND TableB.Total_Amount = TableA.Total_Amount
)

select Id
from (
select Id, Month_Id, Customer_Id, Total_Amount from TableA
except
select Id, Month_Id, Customer_Id, Total_Amount from TableB
) q

SELECT id FROM
(SELECT id, month_id, customer_id, total_ammount FROM TableA
EXCEPT
SELECT id, month_id, customer_id, total_ammount FROM TableB);

You can use the EXCEPT set operator:
SELECT id
FROM (SELECT * FROM table_a
EXCEPT
SELECT * FROM table_b) t

You can use Merge with WHEN NOT MATCHED
place your condition in ON <merge_search_condition>

SELECT Id FROM TableA A LEFT JOIN tableB B
ON A.Id=B.Id AND A.Month_Id =B.Month_Id
AND A.Customer_Id =B.Customer_Id
AND A.Total_Amount=b.Total_Amount
WHERE B.Id is NULL

In oracle sql it would be:
SELECT ID FROM
(SELECT ID, Month_Id, Customer_Id, Total_Amount FROM TABLE_A
MINUS
SELECT ID, Month_Id, Customer_Id, Total_Amount FROM TABLE_B);
Is this what you want?
(Not sure of MINUS operator in sql-server though)

Related

return 0 in select count when no record found

i'm trying to get an id , and a count in same query result.
the problem is when the record doesn't exist , the count return null instead of 0
this is the query
SELECT DISTINCT Id
,(
SELECT count(*)
FROM table1
WHERE reference_id = 300000009798620
)
FROM table1
WHERE reference_id = 300000009798620;
Just use:
SELECT max(id) as id, count(*)
FROM table1
WHERE reference_id = 300000009798620
Please try the below modified query
SELECT 300000009798620 as reference_id, count(*)
FROM table1 WHERE reference_id = 300000009798620
Would this do?
table1 CTE represents your table; I simplified REFERENCE_ID. Both rows share the same reference_id value (1), with two different ID column values (1 and 2)
temp1 selects IDs for par_reference_id parameter value
temp2 counts rows for par_reference_id
First execution returns something as par_reference_id = 1 (count is 2):
SQL> with
2 table1 (id, reference_id) as
3 -- this represents your TABLE1 (but reference_id is way simpler)
4 (select 1, 1 from dual union all
5 select 2, 1 from dual),
6 temp_1 as
7 -- distinct IDs per desired reference_id
8 (select distinct id
9 from table1
10 where reference_id = &&par_reference_id
11 ),
12 temp_2 as
13 -- number of rows for that reference_id
14 (select count(*) cnt
15 from table1
16 where reference_id = &&par_reference_id
17 )
18 -- and finally:
19 select b.id, a.cnt
20 from temp_2 a left join temp_1 b on 1 = 1;
Enter value for par_reference_id: 1
ID CNT
---------- ----------
1 2
2 2
Let's try some other reference_id value (which doesn't exist in table1), e.g. 100: query doesn't return any ID, but count = 0 (as you wanted):
SQL> undefine par_reference_id
SQL> /
Enter value for par_reference_id: 100
ID CNT
---------- ----------
0
SQL>
You can use DUAL to always get a row back with your ID, then a subquery to get the count.
SELECT 300000009798620 AS id,
(SELECT COUNT (*)
FROM table1
WHERE reference_id = 300000009798620) AS amt
FROM DUAL;

Count on UNION in Oracle

I have 3 table and I need to get the details from 2 tables where the count of UNION is greater than 1.But need to apply certain conditions as well
Table A
id entity_id name category
1 45 abcd win_1
2 46 efgh win_2
3 47 efgh1 win_2
4 48 dfgh win_5
5 49 adfgh win_4
Table B
id product_id name parent_id
1 P123 asdf win_1
2 P234 adfgh win_4
Table 3 category_list
id cat_id name
1 win_1 Households
2 win_2 Outdoors
3 win_3 Mixed
4 win_4 Omni
Now I need to have the count of UNION from Table A and Table B where they have count of cat_id greater than 1 and Table A.name != Table B.name
The result which I require is
p_id name cat_id
45 abcd win_1
P123 asdf win_1
46 efgh win_2
47 efgh1 win_2
win_5 is excluded as the count is one and win_4 should be excluded as name in Table A nd B is same.
I have run out of Ideas as i am relatively new to Oracle and DB.Any help is appreciated.
I think you can use exists to ensure that the cat_id is present in both tables
select entity_id as p_id, name, category as cat_id
from table_a a
where exists (select null from table_b where a.category = table_b.parent_id)
union
select entity_id, name, parent_id
from table_b b
where exists (select null from table_a where b.parent_id = table_a.category)
I believe you are looking for something like this -
Select T2.*
from
(Select category
from
(Select name, category from TableA
Union all
Select name, parent_id as category from TableB) t
group by category
having count(distinct name) > 1) T1
Join
(Select entity_id as Pid, name, category from TableA
Union
Select product_id as Pid, name, parent_id as category from TableB) T2
ON T1.category = T2.category;
Would you try this code.
First CTE (Common Table Expression) "list_union" gets the records for each table those have different names then makes the union. with the second CTE "list_cnt" counts the categories and finally gets the result cnt>1 with the last select statement as you pictured.
With
list_union AS (
SELECT
id,
----------
TO_CHAR(entity_id) entity_id,
----------
name,
category
FROM table_A a
WHERE NOT EXISTS(SELECT 1 FROM table_B b WHERE a.name=b.name)
----------
UNION ALL
----------
SELECT
id,
product_id,
name,
parent_id
FROM table_B b
WHERE NOT EXISTS(SELECT 1 FROM table_A a WHERE a.name=b.name)
)
,list_cnt AS (
SELECT
l.*,
----------
COUNT(*) over (PARTITION BY category) cnt
----------
FROM list_union l
)
SELECT
entity_id AS p_id,
name,
category AS cat_id
FROM list_cnt
WHERE cnt>1
ORDER BY cat_id ASC, p_id ASC
;
Just use a union all and window functions:
select ab.*
from (select ab.*,
count(distinct name) over (partition by category) as cnt
from ((select a.* from a
) union all
(select b.* from b
)
) ab
) ab
where cnt > 1;
Although you describe the problem as:
Now I need to have the count of UNION from Table A and Table B where they have count of cat_id greater than 1 and Table A.name != Table B.name
You seem to just want cat_ids that have different names across the two tables. Your sample data includes cat_id = 'win_2', which is not even in the second table.

Getting all the values in one query that aren't in another with a group by

Given that I am using Redshift, how would I get the counts for a query that asks:
Given table A and table B, give me all the count of values in Table A for that grouping that aren't in table B;
So if table A and B look like:
Table A
Id | Value
==========
1 | "A"
1 | "B"
2 | "C"
And table B:
Id | Value
==========
1 | "A"
1 | "D"
2 | "C"
I would want:
Id | Count
==========
1 | 1
2 | 0
You can use left join and group by:
select a.id, sum( (b.id is null)::int )
from a left join
b
on a.id = b.id and a.value = b.value
group by a.id;
Use except and subquery
with a as
(
select 1 as id, 'A' as v
union all
select 1,'B'
union all
select 2,'C'
),b as
(
select 1 as id, 'A' as v
union all
select 1,'D'
union all
select 2,'C'
), c as
(
select id,v from a except select id,v from b
)
select id,sum ( (select count(*) from c where c.id=a.id and c.v=a.v))
from a group by id
output
id cnt
1 1
2 0
online demo which will work in redshift

How to select in SQL Server 2008

Have an issue
Examle
ID ID2
1 100
3 100
5 100
1 110
2 110
4 110
select * from table where ID in (1,4) ---executing not correctly
select * from table where ID = '1' and ID = '4' ---not work
I need that ID2 will '110' (select ID2 which have 2 value ID)
Thanks.
If you have few ID's you can use EXISTS:
SELECT ID, ID2
FROM dbo.Table1 t1
WHERE EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=1 AND t2.ID2=t1.ID2
)
AND EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=4 AND t2.ID2=t1.ID2
)
AND ID IN (1, 4)
This returns the two records that have the same ID2 and ID=1 AND ID=4.
ID ID2
1 110
4 110
Demo-Fiddle
SELECT ID FROM (
SELECT ID, COUNT(*) OVER(PARTITION BY ID2) as cnt FROM Table) t
WHERE t.cnt>1

t-sql query to get all the rows from Table_A which have at least one matching relatedid in Table_B

Based on the below tables
Table_A
Id RelatedId
---------------
1 1
1 2
1 3
2 4
2 5
2 2
3 7
3 8
4 9
Table_B
RelatedId Name
--------------
2 A
3 B
I want to get all the rows from Table_A which have at least one matching relatedid in Table_B. The Ids from Table_A that do not have match in Table_B will have single row in the result table.
So output (result table) in this case will be
Id RelatedId
---------------
1 1
1 2
1 3
2 4
2 5
2 2
3 Null
4 Null
EDIT: Seems like the question text is confusing for many. So a detailed explanation:
Table_A Id 1 has both 2 and 3 (Related Ids) matching in table_B. So output will have all the rows for 1 from Table_A. Similary Id 2 from Table_A has 2 (Related Id) matching in table_B. So all rows corresponding to 2 from Table_A will be picked up. Since 3 does not have any matching relatedid in table_B it will be displayed but with NULL as relatedid in the results table.
with validids as (
select distinct id
from Table_A
inner join Table_B on
Table_A.relatedid = Table_B.relatedid
)
select
id,
relatedid
from Table_A
where id in (select id from validids)
union
select distinct
id,
null
from Table_A
where id not in (select id from validids)
Try:
Select Distinct Id, Related_Id
From Table_A
Where Related_Id In
(Select Related_Id From Table_B)
This should do what you want:
with IdsWithMatchInB(Id) as (
select distinct
Id
from Table_A
where Table_A.RelatedId in (
select Table_B.RelatedId
from Table_B
)
)
select
Table_A.Id,
CASE WHEN IdsWithMatchInB.Id IS NULL
THEN NULL
ELSE Table_A.RelatedId END AS RelatedId
from Table_A
left outer join IdsWithMatchInB
on IdsWithMatchInB.Id = Table_A.Id
Here's another option that avoids DISTINCT by putting the subquery inside the CASE expression:
select
Id,
case when Id in (
select Id
from Table_A as Acopy
where Acopy.RelatedId in (
select
RelatedId
from Table_B
)
)
then RelatedId
else null end as RelatedId
from Table_A;
One or the other might be more efficient for your particular data and indexes.