Compare two columns one of them with sum function - sql

I have two table
table1
table1 contains columns (id,item,quantity1) id PK
The other table
table2
table2 contains columns (no,quantity2,id) id FK
I want to compare quantity1 from table1 with sum(quantity2) from table2(find the same result in quantity1 and quantity2
I mean I want to give me result of quantity1 with the same result in quantity2
quantity1 quantity2
20 20
5 5
I try this but it doesn't work(error in syntax)
SELECT table1.id, table1.quantity1,
table1.item, SUM(table2.quantity2) AS Expr1
FROM table1 INNER JOIN
table2 ON table1.id = table2.id
where table1.quantity1 = Expr1
GROUP BY table1.id, table1.quantity1, table1.item

You can go step by step approach for more clarity. You can use CTE and then join.
;WITH CTE_Table2 AS
(
SELECT id,Sum(quantity2) as quantity_sum
FROM Table2
GROUP BY id
)
SELECT t1.id, t1.quantity1, t1.item, t2.quantity_sum
FROM Table1 AS t1
INNER JOIN CTE_Table2 AS t2
ON t2.id = t1.id
AND t2.quantity_sum = t1.quantity1

To compare aggregates use HAVING:
SELECT table1.id
,table1.quantity1
,table1.item
,SUM(table2.quantity2) AS Expr1
FROM table1
INNER JOIN table2 ON table1.id = table2.id
GROUP BY table1.id, table1.quantity1, table1.item
HAVING SUM(table2.quantity2)=table1.quantity1

Related

Left join table with max value and other column from second table

I have two tables with structure similar to this:
table1
ID |Field1|Field2
table2
ID|Table1_ID|Date|Notice
I need to left join these tables in MS Access SQL based on max date from second table, but also to include 'Notice' field in new table, so result should be like this:
ID|Field1|Field2|Max_Date|Notice
I can join tables based on max date like this:
SELECT t1.ID, t1.Field1, t1.Field2, t2.Max_date
FROM table1 AS t1
LEFT JOIN
[SELECT Table1_ID, MAX(Date) AS Max_date
FROM table2
GROUP BY Table1_ID] AS t2
ON t1.ID = t2.Table1_ID
How can I include 'Notice' field in this query too?
JOIN again:
SELECT t1.ID, t1.Field1, t1.Field2, t2m.Max_date, t2.Notice
FROM (table1 AS t1 LEFT JOIN
(SELECT Table1_ID, MAX(Date) AS Max_date
FROM table2
GROUP BY Table1_ID
) AS t2m
ON t1.ID = t2m.Table1_ID
) LEFT JOIN
table2 as t2
ON t2.Table1_ID = t2m.Table1_ID AND t2.Date = t2m.Max_Date

SQL Query, how to get data from two tables

Table 1:
ID (unqiue), Name, Address
Table 2:
RecordId, ID (key of table 1), Child name
In one query, I want to retrieve all rows of Table 1 with one additional column which will be the count of all record in table 2 from ID (that is number of children for each ID in table 1). Can't figure out how to format a query to retrieve this data.
Simply Join and apply count
select T1.*, COUNT(T2.RECORDID)AS T2COUNT from Table1 T1
INNER JOIN TABLE2 T2 ON T1.ID= T2.ID
--LEFT JOIN TABLE2 T2 ON T1.ID= T2.ID --if you need 0 child records (from commets by #Cha)
GROUP BY T1.ID , T1.Name, T1.Address
The correct way of doing this will be with a OUTER JOIN:
SELECT a.ID, a.Name, a.Address, b.cnt
FROM Table1 a
LEFT OUTER JOIN
(SELECT ID, count(*) cnt from Table2 GROUP BY ID) b
ON a.ID = b.ID
The incorrect way will be with a help of a correlated sub-query:
SELECT a.ID, a.Name, a.Address,
(SELECT count(*) FROM Table2 b WHERE b.ID = a.ID) as cnt
FROM Table1 a
Here is a discussion about correlated subqueries vs OUTER JOINs, if you are interested
Group by table1 fields and count total records in table2:
here T1 alias of table1 and T2 alias of table2.
select T1.ID, T1.Name, T1.Address, count(T2.ID) as total_records
from table1 as T1
left outer join table2 as T2 on T2.ID=T1.ID
group by T1.ID, T1.Name, T1.Address

Applying joins conditionally in SQL Server

I have some set of records, but now i have to select only those records from this set which have theeir Id in either of the two tables.
Suppose I have table1 which contains
Id Name
----------
1 Name1
2 Name2
Now I need to select only those records from table one
which have either their id in table2 or in table3
I was trying to apply or operator witin inner join like:
select *
from table1
inner join table2 on table2.id = table1.id or
inner join table3 on table3.id = table1.id.
Is it possible? What is the best method to approach this? Actually I am also not able to use
if exist(select 1 from table2 where id=table1.id) then select from table1
Could someone help me to get over this?
Use left join and then check if at least one of the joins has found a relation
select t1.*
from table1 t1
left join table2 t2 on t2.id = t1.id
left join table3 t3 on t3.id = t1.id
where t2.id is not null
or t3.is is not null
I would be inclined to use exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.id = t1.id) or
exists (select 1 from table3 t3 where t3.id = t1.id) ;
The advantage to using exists (or in) over a join involves duplicate rows. If table2 or table3 have multiple rows for a given id, then a version using join will produce multiple rows in the result set.
I think the most efficient way is to use UNION on table2 and table3 and join to it :
SELECT t1.*
FROM table1 t1
INNER JOIN(SELECT id FROM Table2
UNION
SELECT id FROM Table3) s
ON(t.id = s.id)
Alternatively, you can use below SQL as well:
SELECT *
FROM dbo.Table1
WHERE id Table1.IN ( SELECT table2.id
FROM dbo.table2 )
OR Table1.id IN ( SELECT table3.id
FROM Table3 )

sql left outer join order by column in left table but preserve all rows

I have the following:
SELECT
table1.id
FROM
table1
LEFT OUTER JOIN table2 ON table2.table1_id = table1.id
WHERE
(table1.entry_id=2)
AND
parent_id=0
ORDER BY
SUM(table2.column1) - SUM(table2.column2)
Works fine until I add the 'order by', I need it to get all relevant rows from table1, even if they have unmatched rows in table2, ordering would place them at the bottom.
Try this instead:
SELECT
t1.id
FROM table1 AS t1
LEFT OUTER JOIN
(
SELECT table1_id, SUM(column1) sum1, SUM(column2) sum2
FROM table2
GROUP BY table1_id
) AS t2 ON t2.table1_id = t.id
AND t1.entry_id = 2
AND t1.parent_id = 0
ORDER BY t2.sum1 - t2.sum2;

get all rows from one table, sum on column from a second table using a where clause

I want to get all rows from table1 and I want to get a total of a column in table3 for each person in table1. I am able to do this if I don't use a where clause anywhere in my query (in the sub select, inner join or regular where clause). If I use a where clause like below, only the people in table1 that have records in table2 between a supplied date and have been verified.
What I want is all rows from table1 but sum only the records in table2 that are between the supplied date and have been verified.
Is there any way to do this in a single query?
SELECT table1.ID
, table1.LName
, table1.FName
, (Select SUM(table3.DollarValue) Where table2.Verified = 1) AS total
FROM table3
INNER JOIN table2 ON table3.IncentiveID = table2.IncentiveID
RIGHT OUTER JOIN table1 ON table2.ID = table1.ID
Where table2.date >= '1/1/2012'
AND table2.date <= '12/31/2012'
AND table2.Verified = 1
Group By table1.ID, table1.LName, table1.FName, table2.Verified
Order By table1.LName, table1.FName
Thank you in advance for any help!
Based on your description, it sounds like you want something like the following. Which places your table2 and table3 join and sum() in a subquery with the WHERE filtering and then joins that result to table1:
SELECT t1.ID,
t1.LName,
t1.FName,
IsNull(t.total, 0) as Total
FROM table1 t1
LEFT JOIN
(
SELECT t2.id, SUM(t3.DollarValue) as total
FROM table2 t2
INNER JOIN table3 t2
on t2.IncentiveID = t3.IncentiveID
WHERE t2.date >= '2012-01-01'
AND t2.date <= '2012-12-31'
AND t2.Verified = 1
GROUP BY t2.id
) t
on t1.ID = t.ID
Order By t1.LName, t1.FName;