I need a query that returns rows from table A if value X in table A is not the same as the sum of value Y from corresponding row(s) in table B. The issue is that there may or may not be rows in table B that correspond to the rows in table A, but if there no rows in table B, then the rows from table A should still be returned (because there is not a matching value in table B.) So it is like a LEFT OUTER join scenario, but the extra complication of having a comparison as an additional selection criteria.
I have a query that does the opposite, ie. returns rows if the value in table A is the same as the value of row(s) in table B, but sadly this isn't what I need!
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
WHERE TableA.select_field = 408214
AND TableA.planned_volume =
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id
Any help greatly appreciated.
How about something like this:
SELECT TableA.Id, TableA.bdate
FROM TableA
LEFT JOIN
(
SELECT Id, SUM(actual_volume) AS b_volume
FROM TableB
GROUP BY Id
) AS TableBGrouping
ON TableBGrouping.Id= TableA.Id AND TableA.planned_volume <> b_volume
ORDER BY TableA.Id
WITH TotalVolumes
AS
(
SELECT id, SUM(actual_volume) AS total_volume
FROM TableB
GROUP
BY id
)
SELECT id, bdate, planned_volume
FROM TableA
EXCEPT
SELECT A.id, A.bdate, T.total_volume
FROM TableA AS A
JOIN TotalVolumes AS T
ON A.id = T.id;
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
AND TableA.planned_volume <>
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id
Related
I have a SQL Server query for an inner join...
SELECT *
FROM tableA
INNER JOIN tableB on tableA.my_id = tableB.my_id
How would I find all the records that did NOT match in this join?
You can use a FULL JOIN to combine the two tables, then use a WHERE clause to filter the results down to only non-matching rows by checking for a NULL in each tables primary key value.
Full outer join All rows in all joined tables are included, whether they are matched or not.
SELECT a.pk, b.pk
FROM tableA a
FULL JOIN tableB b ON a.pk=b.fk
WHERE
a.pk IS NULL
OR b.pk IS NULL
SELECT A2.* FROM TableA A2
WHERE A2.my_id NOT IN
(Select tableA.my_id FROM
tableA
inner join
tableB
on tableA.my_id = tableB.my_id)
you could similarly do the above starting SELECT B2.* FROM TableB B2, in order to separately query unmatched records in Table B
if you want all records in one table you could UNION ALL the two queries, depending on the table field structures being the same or how you specify the fields you select - what are you doing with the data?
SELECT * FROM tableA where my_id NOT IN (SELECT my_id from tableB)
UNION ALL
SELECT * FROM tableB where my_id NOT IN (SELECT my_id from tableA)
I have a query that looks to match 6 fields between two tables and return the matches. This query uses inner joins. I've been testing INTERSECT to replace this. Thus,
SELECT Field1, Field2, Field3,...,Field6
FROM TableA
INTERSECT
SELECT Field1, Field2, Field3,...,Field6
FROM TableB
However, I want to add TableA.ID and TableB.ID to the results and can't quite get it written where the query won't take forever (relative to the original query). Any thoughts?
UPDATE:
Regretfully, I added the comment about performance when the first concern is how to properly write the query. As you can see, I believe the main issue is the very bad and incorrect query structure that I just haven't been able to improve. My attempt:
SELECT a.ID, b.ID
FROM TableA a
INNER JOIN
(
SELECT Field1, Field2, Field3,...,Field6
FROM TableA
INTERSECT
SELECT Field1, Field2, Field3,...,Field6
FROM TableB
) Dupes ON
(
a.Field1 = Dupes.Field1 and
...
a.Field6 = Dupes.Field6
)
INNER JOIN TableB b
(
b.Field1 = Dupes.Field1 and
...
b.Field6 = Dupes.Field6
)
A simple INNER JOIN on all 6 fields will return all records from both tables having common field values:
SELECT A.ID, B.ID, A.Field1, A.Field2, A.Field3, A.Field4,
A.Field5, A.Field6
FROM TableA AS A
INNER JOIN TableB AS B
ON A.Field1 = B.Field1 AND A.Field2 = B.Field2 AND A.Field3 = B.Field3 AND
A.Field4 = B.Field4 AND A.Field5 = B.Field5 AND A.Field6 = B.Field6
To optimize the above query you need to set indices on all columns used in the ON clause of the INNER JOIN.
I have two query which has successfully inner join
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
The above query will return me the name and the corresponding number of count and the sum. I need to do a comparison between the count and sum. If the count doesnt match the sum, it will return 0, else 1. And so my idea was implementing another outer layer to wrap them up and use CASE WHEN. However, I've failed to apply an outer layer just to wrap them up? This is what I've tried:
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
)
Alright the problem can be solved by simply assigning a name to the outer layer.
select * from(
select t1.countResult, t2.sumResult from (
select
count(column) as countResult
from tableA join tableB
on tableA.id = tableB.id
group by name
)t1 inner join (
select
sum(column) as sumResult
from tableA
join tableB
on tableA.id = tableB.id
group by name
)t2
on t1.name= t2.name
) as whatever //SQL Server need a name to wrap
Hope it will help any newbie like me
Ok, so far you have selected everything your first select has generated (kinda useless, but a start for what you want ;) )
SELECT CASE
WHEN countresult=sumresult THEN 'Equal'
ELSE 'Not'
END
FROM ( --your join select --
)
I don't have any sample data to test this so can just go on your code.
Your queries for t1 & t2 look identical - why don't you just do a sum & count in 1 step?
SELECT COUNT(column) AS countResult
,SUM(column) AS sumResult
FROM tableA INNER JOIN tableB
ON tableA.id = tableB.id
GROUP BY name
Also, as you mention you are a newb - read up on Common Table Expressions in SQL Server.
Before SQL 2005 you had to write these convoluted queries within queries within...
Get into the habit of using CTEs now.
I have two tables:
Table A
ID Name
1 abc
2 xyz
Table B
ID Name
1 abc
2 xyz
3 mno
I need the distinct value form above two table, I mean i want only ID 3 Name mno from Table B (as it is unique from two table)
Please let me know how I can get this value.
Thanks,
Ajay
This query will get you the rows from B that don't exist in A:
SELECT b.* FROM TableB b
OUTER JOIN TableA a ON a.ID = b.ID AND a.Name = b.Name
WHERE a.ID IS NULL
you could then do the adverse and use a UNION ALL to get it both ways:
SELECT a.* FROM TableA a
OUTER JOIN TableB b ON b.ID = a.ID AND b.Name = a.Name
WHERE b.ID IS NULL
UNION ALL
SELECT b.* FROM TableB b
OUTER JOIN TableA a ON a.ID = b.ID AND a.Name = b.Name
WHERE a.ID IS NULL
Another way of achieving it would be:
;WITH MatchingRows AS (
SELECT a.ID FROM TableA a
JOIN TableB b ON b.ID = a.ID AND b.Name = a.Name
)
SELECT * FROM TableA
WHERE ID NOT IN (SELECT m.ID FROM MatchingRows m)
UNION ALL
SELECT * FROM TableB
WHERE ID NOT IN (SELECT m.ID FROM MatchingRows m)
I'm not sure if that performs better or not - it's just something I thought of. If I'm not mistaken this will actually run the WITH query twice (see the answer to this question) because it's being used twice - so there may be some performance implications with this approach.
The EXCEPT operator may work for you. Here is an example using your data.
CREATE TABLE TableA (id int, name varchar(50))
INSERT INTO TableA VALUES (1, 'abc'),(2,'xyz')
CREATE TABLE TableB (id int, name varchar(50))
INSERT INTO TableB VALUES (1, 'abc'),(2,'xyz'),(3,'mno')
SELECT * FROM TableB
EXCEPT
SELECT * FROM TableA
Be warned though it acts like UNION. It's only going to exclude rows where there is an exact match on all columns.
I have three tables such as TableA, TableB and TableC. I want to update one column in TableA from the column value in TableC. But there is no direct relationship b/w TableA and TableC. But TableB has relationship with both the tables A and C. How can I update? The structure of the tables are given below:
TableA: TableB: TableC:
---------- ----------- ----------
ItemID ID ID
Name ItemDetailID D1
Quantity TotalQty D2
Rate TotalAmount D3
ItemDetailID TotalWeight Quantity
Here I want to update TableA Column "Quantity" with TableC column value "Quantity".
I used Update select statement using two tables. But not like this. How to do? Please give suggestions...
Something like:
Update a
set a.Quantity = c.Quantity
from TableA a
join TableB b on b.ItemDetailId = a.ItemDetailId
join TableC c on c.ID = b.ID
Update a
Set a.Quantity = c.Quantity
From TableA a
Inner Join TableB b on b.ItemDetailId = a.ItemDetailId
Inner Join TableC c on c.ID = b.ID