comparing two tables and removing ones that match - sql

I have two tables. MembID is the only column returned for each. The MembID can be in both tables but I would like to remove the ones that are in both from the results.
I'd like the final return to be 456 and 789 from Table A.
I've tried:
select distinct a.membid
from a
left join b on a.membid = b.membid
and b.num <> 1
it does not return any results.
Thanks.

try like below
select distinct a.membid
from a
left join b on a.membid = b.membid
where b.membid is null

The MembID can be in both tables but I would like to remove the ones that are in both from the results.
If you want members in only one table, here is one method:
select memberid
from ((select memberid, 1 as in_a, 0 as in_b from a
) union all
(select memberid, 0, 1 from b
)
) ab
group by memberid
having max(in_a) + max(in_b) = 0;
Note that this version allows duplicates within each table.
In databases that support set-based operators, you can also do:
(select memberid from a union
select memberid from b
) except -- sometimes this is minus
(select memberid from a intersect
select memberid from b
);
EDIT:
Your description of the problem doesn't match your data. You seem to want the members in a that are not in b. One method elaborates on the first:
select memberid
from ((select memberid, 1 as in_a, 0 as in_b from a
) union all
(select memberid, 0, 1 from b
)
) ab
group by memberid
having max(in_a) + max(in_b) = 0;
Or the second:
select memberid from a
except -- or minus
select memberid from b
However, I would typically do:
select distinct memberid
from a
where not exists (select 1 from b where b.memberid = a.memberid);

Related

Return groupings where at least one row per group satisfies a condition SQL server

I have a table (let's call it TableA) with multiple columns, Id being the unique id one.
I'm only interested in three: A (int), B (int), C (varchar).
Initially I want to pick up the rows which share the same A and B and return at least 2 rows.
; WITH CTE AS (
SELECT tbl.A, tbl.B
FROM [dbo].[TableA] tbl
/* WHERE irrelevant filter here */
GROUP BY tbl.A, tbl.B
HAVING COUNT(1) > 1
)
From this point on, I want to return the groupings identified in this CTE where AT LEAST one row in each grouping has it's C column set to 'ThisValue'.
Use sum with case to count the records that have 'ThisValue'
; WITH CTE AS (
SELECT tbl.A, tbl.B
FROM [dbo].[TableA] tbl
/* WHERE irrelevant filter here */
GROUP BY tbl.A, tbl.B
HAVING COUNT(1) > 1 and sum(case tbl.C when 'ThisValue' then 1 else 0 end)>0
)
You can, for example, use EXISTS operator.
; WITH CTE AS (
SELECT tbl.A, tbl.B
FROM [dbo].[TableA] tbl
/* WHERE irrelevant filter here */
GROUP BY tbl.A, tbl.B
HAVING COUNT(1) > 1
)
SELECT * FROM CTE
WHERE EXISTS (SELECT 1 FROM [dbo].[TableA] tc
WHERE tc.A=CTE.A AND tc.B=CTE.B AND tc.C='ThisValue');

How to exclude some (not all) record that has same values

After query table A using first query, I have these records:
pID cID code
1 1 A
1 1 B
1 1 B
1 1 B
After query table B using second query, I have one record:
pID cID code
1 1 B
1 1 B
I want table A exclude the records of table B. The result is:
pID cID code
1 1 A
1 1 A
How can I do that? Hope u could help me. thanks.
Updating...
Sorry for the example to make you confuse
If I got these record from second table:
pID cID code
1 1 B
Then the result I want is (exclude one record):
pID cID code
1 1 A
1 1 B
1 1 B
you try GROUP BY function in your Query
example :
select pID,cID,code from table group by code
using EXCEPT and row_number() to generate a unique no
;with cte1 as
(
select *, rn = row_number() over (partition by pID, cID, code order by pID, cID, code)
from query1
),
cte2 as
(
select *, rn = row_number() over (partition by pID, cID, code order by pID, cID, code)
from query2
)
select *
from cte1
except
select *
from cte2
Based on your question, which I think you want to delete the records from B which occur more than once in A:
first select all records from A which are not there in B and then union them 1 distinct records which are there in both A and B:
select * from A
except
select * from B
union all
select distinct *
from
(select a.pid, a.cid, a.code
from
A
inner join
B
on a.pid=b.pid and a.cid=b.cid and a.code=b.code)
Just use EXCEPT. How ever your desired output is wrong as 1 1 B also the same record from TableB
SELECT * FROM TABLE_A
EXCEPT
SELECT * FROM TABLE_B
Refer this Link
If your case NOt all But some then.
Simply you can use DISTINCT
As per the UPdate in Question (From what I understood)
SELECT DISTINCT * FROM TABLE_A
UNION ALL
SELECT * FROM TABLE_B

Count uid from two tables who look the same sort by tablename

since I am not as good with more complex SQL SELECT Statements I thought of just asking here, since it's hard to find something right on topic.
I got two tables who have exactly the same structure like
TABLE A (id (INT(11)), time (VARCHAR(10));)
TABLE B (id (INT(11)), time (VARCHAR(10));)
Now I want a single SELECT to count the entrys of an specific id in both tables.
SELECT COUNT(*) FROM TABLE A WHERE id = '1';
SELECT COUNT(*) FROM TABLE B WHERE id = '1';
So I thought it would be much better for the database performance if I use one SELECT instead of one.
Thanks for helping out
SELECT COUNT(*) as count, 'tableA' as table_name FROM TABLEA WHERE id = '1'
union all
SELECT COUNT(*), 'tableB' FROM TABLEB WHERE id = '1'
If you want the separate counts in a single row, you can use subqueries
SELECT
(SELECT COUNT(*) FROM TABLE A WHERE id = '1') a_count,
(SELECT COUNT(*) FROM TABLE B WHERE id = '1') b_count;
You could do it like:
select count(*)
from (
select id from t1 where id = 1
union all
select id from t2 where id = 1
) as t
Another alternative is:
select sum(cnt)
from (
select count(*) as cnt from t1 where id = 1
union all
select count(*) as cnt from t2 where id = 1
) as t

How to get Original Rows filtered by a HAVING Condition?

What is the method in T-SQL to select the orginal values limited by a HAVING attribute. For example, if I have
A|B
10|1
11|2
10|3
How would I get all the values of B (Not An Average or some other summary stat), Grouped by A, having a Count (Occurrences of A) greater than or equal two 2?
Actually, you have several options to choose from
1. You could make a subquery out of your original having statement and join it back to your table
SELECT *
FROM YourTable yt
INNER JOIN (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
) cnt ON cnt.A = yt.A
2. another equivalent solution would be to use a WITH clause
;WITH cnt AS (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
)
SELECT *
FROM YourTable yt
INNER JOIN cnt ON cnt.A = yt.A
3. or you could use an IN statement
SELECT *
FROM YourTable yt
WHERE A IN (SELECT A FROM YourTable GROUP BY A HAVING COUNT(*) >= 2)
A self join will work:
select B
from table
join(
select A
from table
group by 1
having count(1)>1
)s
using(A);
You can use window function (no joins, only one table scan):
select * from (
select *, cnt=count(*) over(partiton by A) from table
) as a
where cnt >= 2

Select rows with multiple occurrences over multiple tables

DB: SQL Server 2008
I want to select id, title and userid from a table if that userid occurs more than once across 2 tables.
So if a user has 2 records in locations table, and 1 in artists table, i want to return the id, title and userid of all 3 records.
This is what I have now, but it returns 0 records.
When I leave out the "having count(userid)>1" part, I get ALL 400 records in all tables.
select userid,id,title from (
select id,title,userid from locations l
union
select id,title,userid from artists a
) as info
group by userid,id,title
having count(userid)>1
Something like this should work:
select userid,id,title
from
( select id,title,userid from locations l union select id,title,userid from artists a )
as grabfromthis
where userid in (
select userid
( select id,title,userid from locations l union select id,title,userid from artists a )
as info
group by userid having count(userid)>1)
I modified the above slightly to make it just a bit more slick:
WITH combined AS
(
SELECT id from t1
UNION ALL
SELECT id FROM t2
etc...
)
SELECT id, count(id) as numOccurrences
FROM combined
GROUP BY id
HAVING count(id) > 1
The difference being that this will show you just how many times your number is repeated.
You could also add
ORDER BY numOccurrences to chop down your worst offenders first
;WITH combined AS (
SELECT id, title, userid FROM locations
UNION ALL
SELECT id, title, userid FROM artists
)
SELECT *
FROM combined c
INNER JOIN (
SELECT userid
FROM combined
GROUP BY userid
HAVING COUNT(*) > 1
) g ON c.userid = g.userid
Get the non-unique userid list from the UNION sub-query and join it back to the subquery on userid. The sub-query is implemented only once, as a CTE.