SQL to sum a total of a column where 2 columns match in a different table - sql

SO I have 2 tables and would like to SUM the total of a column in one table where 2 other columns match in another table.
In table1 I have acc_ref and bill_no.
acc_ref is different but bill_no could be 1-10 (so 2 or more acc_ref could have the same bill_no)
In table2 I have acc_ref, bill_no and tran_amnt.
Εach acc_ref has multiple rows and I want to SUM the tran_amnt but only if acc_ref and bill_no both match in table1.
I tried this but I get an error
'The columns in the SELECT clause must be contained in the GROUP BY
clause'
select a.acc_ref, a.bill_no
from table1 a
where exists (select acc_ref, bill_no, SUM (tran_amount)
from table2 b
where a.acc_ref = b.acc_ref
and a.bill_no = b.bill_no
group by acc_ref)
Apologies if this is very basic and obvious but I'm struggling!!

In you description it seems like table1 does not contain any useful information. Because both columns you give also exist in table2. So if nothing else from table1 is needed, you could just remove table1 from the query). Still with your problem you should do a simple join
SELECT a.acc_ref, a.bill_no, SUM(b.tran_amount)
FROM table1 a
JOIN table2 b ON b.acc_ref = a.acc_ref AND b.bill_no=a.bill_no
GROUP BY a.acc_ref, a.bill_no

I believe you should use case:
Sample:
SELECT
TABEL1.Id,
CASE WHEN EXISTS (SELECT Id FROM TABLE2 WHERE TABLE2.ID = TABLE1.ID)
THEN 'TRUE'
ELSE 'FALSE'
END AS NewFiled
FROM TABLE1

Related

How to correctly sum the values for a unique ID with the condition

How to sum the values in Number field in table2 when the ID field is unique and field Type = 3 (range 1-5)?
SELECT TOP (100)
TB1.CarID
FROM table1 as TB1
LEFT JOIN table2 as TB2 on TB1.CarID = TB2.CarID
WHERE
GROUP BY
Table1
Table2
I have tried several solutions:
,SUM (CASE WHEN TB2.Type = 3 THEN TB2.Number END)
Return result is incorrect x2, possibly due to a large number of table joins. If you have any comment why the values are displayed x2, please give me a hint. I would like to add an additional condition, i.e. sum only when the value in the id column is unique. I believe this can solve the problem.
,SUM (CASE WHEN TB2.Type = 3 AND TB2.ID is UNIQUE THEN TB2.Number END) [incorrect]
I will be grateful for your help!
Part of the problem is likely that you join on carid, but that is not unique in Either table.
At present you have 5 copies of 'aaaad' in Table1 and 5 copies in Table2. When you join them, you get 25 rows back (each row in T1 matching against 5 rows in T2).
So, I'd start with aggregating the second table before joining on it...
SELECT
*
FROM
table1 AS t1
LEFT JOIN
(
SELECT
carid,
SUM(number) AS number
FROM
table2
WHERE
type = 3
GROUP BY
carid
)
AS t2
ON t1.CarID = t2.CarID
That way you avoid multiplying the number of rows.

How to JOIN and get data from either table based on specific logics?

Let's say I have 2 tables as shown below:
Table 1:
Table 2:
I want to join the 2 tables together so that the output table will have a "date" column, a "hrs_billed_v1" column from table1, and a "hrs_billed_v2" column from table2. Sometimes a date only exists in one of the tables, and sometimes a date exists in both tables. If a date exists in both table1 and table2, then I want to allocate the hrs_billed_v1 from table1 and hrs_billed_v2 from table2 to the output table.
So the ideal result will look like this:
I've tried "FULL OUTPUT JOIN" but it returned some null values for "date" in the output table. Below is the query I wrote:
SELECT
DISTINCT CASE WHEN table1.date is null then table2.date WHEN table2.date is null then table1.date end as date,
CASE WHEN table1.hrs_billed_v1 is null then 0 else table1.hrs_billed_v1 END AS hrs_billed_v1,
CASE WHEN table2.hrs_billed_v2 is null then 0 else table2.hrs_billed_v2 END AS hrs_billed_v2
FROM table1
FULL OUTER JOIN table2 ON table1.common = table2.common
Note that the "common" column where I use to join table1 and table2 on is just a constant string that exists in both tables.
Any advice would be greatly appreciated!
A full join is indeed what you want. I think that would be:
select
common,
date,
coalesce(t1.hrs_billed_v1, 0) as hrs_billed_v1,
coalesce(t2.hrs_billed_v2, 0) as hrs_billed_v2
from table1 t1
full join table2 t2 using (common, date)
Rationale:
you don't show what common is; your data indicates that you want to match rows of the same date - so I put both in the join condition; you might need to adapat that
there should really be no need for distinct
coalesce() is much shorter than the case expressions
using () is handy to express the join condition when the columns to match have the same name in both tables

Setting a column value in the SELECT Statement based on a value existing in another table

I have 2 tables. One table lists all the records of items we track. The other table contains flags of attributes of the records in the first table.
For example, Table 1 has columns
Tab1ID, Name, Address, Phone
Table 2 has these columns
Tab2ID, Tab1ID, FlagName
There is a 1 to Many relationship between Table1 and Table2 linked by Tab1ID.
I'd like to create a query that has all the records from Table1 in it. However, if one of the records in Table2 has a Flagname=Retired (with a matching Tab1ID) then I want a "Y" to show up in the select column list otherwise an "N".
I think it might look something like this:
Select Name, Address, Phone, (select something in table2)
from Table1
where Tab1ID > 1;
It's the subquery in the column that has me stumped.
Pat
You can use exists:
Select t1.*,
(case when exists (select 1
from table2 t2
where t2.tab1id = t1.tab1id and t2.flagname = 'Retired'
)
then 'Y' else 'N'
end) as retired_flag
from Table1 t1;
I would do a normal join returning multiple records, but convert them to bits with case statements. Then use that as the subquery and pull the max value for each bit column.
select
name
,address
,phone
,max(retired_flag)
from (
select
table1.name
,table1.address
,table1.phone
,case when table2.flagname = 'retired' then 1 else 0 end as [retired_flag]
from table1
left join table2
on table1.tab1id = table2.tab1id
where tab1id > 1
) tbl
group by
name
,address
,phone

Query With Distinct Value

I have two tables Tabel1 and Table2. My tables look something like this.
Table1 has three fields Cust_Number, sales_org and Orders.
Table 2 has fields by name Cust_Number, sales_org, BU and Dist_Channel.
Dist_Channel is missing in table1 hence I have to get the Distinct of Cust_Number and sales_org from TABLE 2 and then do a join with table1 to get the corresponding BU.
I was able to do it in MS access by creating one additional query to pull the distinct Numbers and then using that query in my final query.
Could anybody give some suggestions on this?
SELECT t1.cust_number, t2.bu, t2.dist_channel
FROM table1 t1, table2 t2
WHERE t1.cust_number = t2.cust_number
AND t1.sale_org = t2.sales_org
AND -- your actual criteria go here
Try this simple version :
SELECT t1.cust_number, t1.sales_org, t2.BU
FROM Tabel1 t1
INNER JOIN Table2 t2 ON t1.cust_number= t2.cust_number AND t1.sales_org = t2.sales_org
You can do it like this:-
SELECT tbl1.cust_number, tbl1.sales_org tbl2.bu, tbl2.dist_channel
FROM Table1 as tbl1, Table2 as tbl2
WHERE tbl1.cust_number = tbl2.cust_number
AND tbl1.sale_org = tbl2.sales_org
......
Cust_Number, sales_org, are common in both the table you can do this by left join
also first check distinct count of Cust_Number and sales_org in table 2 is same or not
SELECT Tabel1.Cust_Number, Tabel1.sales_org, Table2.BU FROM Tabel1 left JOIN Table2 ON Tabel1.Cust_Number = Table2.Cust_Number AND Tabel1.sales_org = Table2.sales_org
Santhosa, as I understand the problem, it's that in Table2, you can have multiple rows that have the same customer number and sales org (but different dist_channels) so that a simple join to the table will multiply the number of rows coming out of Table1, which is not what you want. Instead, you want to use Table2 simply as a look up for the BU for a customer number and sales org, and we are assuming that there is a functional dependency from cust_number,sale_org --> BU, i.e. that for any given cust_number, sale_org pair in Table2, the BU is always the same.
If that assumption is true, then you can do the following:
SELECT tb1.cust_number, tb1.sales_org, tb2.bu
FROM Table1 AS tb1
JOIN (
SELECT DISTINCT cust_number, sales_org, bu
FROM Table2) AS tb2
ON tb1.cust_number = tb2.cust_number
AND tb1.sales_org = tb2.sales_org
But keep in mind that if you have multiple BUs for a given cust_number, sales_org pair, then this will still result in multiple rows being returned for a given cust_number, sales_org pair in Table1.

Help with Joins

my first table has about 18K records
so when i
select * from table2 i get about 18k
i'm trying to do a join on it as follows, but i'm getting like 26K back.. what am i doing wrong? i though it's supposed to return all of the "right" aka table2 records plus show me whatever value matches from the first in a separate column...
Select t1.fID , t2.*
FROM table1 t1 right join table2 t2 on t1.fName = t2.f
here is an exmaple of my tables:
table 1:
fID, fName
table 2: id, f, address, etc
i need to get all records from table 2, with an fID column, whenever f=fName
table1 has many rows with a value of fname that matches the same in table2.
Example, say 5k rows table2 have no matching rows in table1, you have a average of 2 rows in table 1 for each of the remaining 13k table2 rows
Because you have also asked for a column for table1, this will happen. You'll note multiple t1.fId values for a given t2.fname. Or NULLs
If t1.fName and t2.f aren't unique identifiers for their tables, you will find that rows from table1 are being joined with multiple rows from table2.
The RIGHT JOIN keyword Return all rows from the right table (table_name2), even if there are no matches in the left table (table_name1).See Right Join
So it looks like you do not have your matching criteria set correctly or you have no matches.
This is possible when some fName values are repeated in Table2 and/or Table 1.
Run these Queries and See:
SELECT fName, COUNT(1) FROM Table2 GROUP BY fName HAVING COUNT(1) > 1
SELECT fName, COUNT(1) FROM Table1 GROUP BY fName HAVING COUNT(1) > 1