SQL Server Get the difference of two queries

z31licg0  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(113)

I have this query in my SQL Server database which returns 11196:

SELECT count(*)
FROM all14020612 AS a

If I rewrite the query and join it with another table it returns 11013 records:

SELECT count(*)
FROM   all14020612 AS a
       INNER JOIN MoshaverinAmlaks AS m
               ON a.[شناسه صنفی] COLLATE SQL_Latin1_General_CP1256_CI_AS = m.SenfID
       INNER JOIN Users AS u
               ON m.Code = u.MoshaverinAmlakCode

I want the 183 records (the difference between these two queries), how can I write it to get these 183 expected records? I tried this query below but It gives me 380 records which is not correct :

SELECT count(*)
FROM   all14020612 AS a
WHERE  NOT EXISTS (SELECT 1
                   FROM   MoshaverinAmlaks AS m
                          INNER JOIN Users AS u
                                  ON m.Code = u.MoshaverinAmlakCode
                   WHERE  m.SenfID = a.[شناسه صنفی] COLLATE SQL_Latin1_General_CP1256_CI_AS)

see I don't want the count of the differences, I want all of the records

bhmjp9jg

bhmjp9jg1#

It looks like there are 380 records in all14020612 unmatched by MoshaverinAmlaks JOIN Users but one or more of the remaining rows in all14020612 join to more than one row when you do the join.

When you subtract the counts you are implicitly assuming that each row in all14020612 joins to exactly one or zero rows but this clearly isn't the case from your results.

( This Fiddle gives example data that generates your stated results ).

You can use the following to get the rows that match 0 or >1 rows to see how this all breaks down.

SELECT *
FROM all14020612 AS a
CROSS APPLY 
(
SELECT COUNT(*)
FROM   MoshaverinAmlaks AS m
        INNER JOIN Users AS u
                ON m.Code = u.MoshaverinAmlakCode
WHERE  m.SenfID = a.[شناسه صنفی] COLLATE SQL_Latin1_General_CP1256_CI_AS
) ca(joined_row_count)
WHERE joined_row_count <> 1
2w3rbyxf

2w3rbyxf2#

You can use a left join rather than inner join. Left joins return all of the records from the left table whereas inner joins only return records that exist in both left and right tables.

SELECT *
FROM all14020612 AS a
    LEFT OUTER JOIN MoshaverinAmlaks AS m ON a.[شناسه صنفی] COLLATE SQL_Latin1_General_CP1256_CI_AS = m.SenfID
    LEFT OUTER JOIN Users AS u ON m.Code = u.MoshaverinAmlakCode
WHERE m.SenfID IS NULL OR u.MoshaverinAmlakCode IS NULL
ohtdti5x

ohtdti5x3#

One possible way would be to use the EXCEPT operator.

The EXCEPT operator is used to return all rows in the first SELECT statement that are not returned by the second SELECT statement.

SELECT a.*
FROM all14020612 AS a

EXCEPT

SELECT a.*
FROM all14020612 AS a
inner join MoshaverinAmlaks AS m
    on a.[شناسه صنفی] COLLATE SQL_Latin1_General_CP1256_CI_AS = m.SenfID
    INNER JOIN Users AS u ON m.Code = u.MoshaverinAmlakCode
;

Why the count of rows in the difference result set is not the same as the count(*) - count(*) .

Let the first query return 10 rows:

1
2
3
4
5
6
7
8
9
10

The COUNT(*) returns 10.

Let the second query return 8 rows with duplicates:

1
2
3
4
5
5
5
5

The COUNT(*) returns 8.

The difference ( EXCEPT ) returns 5 rows

6
7
8
9
10

which is more than 10-8.

Does your table all14020612 have a primary key? You can check if your second query returns duplicates of that primary key. This can happen if there is more than one User , or more than one MoshaverinAmlak for a certain row in all14020612 .

相关问题