Missing data from Left JOIN - sql

I have two tables which I am left joining together.
SELECT Col3, tab1.Col1, tab1.Col2 FROM
(SELECT Col1,Col2
FROM Table1
GROUP BY Col1,Col2) tab1
LEFT JOIN
(SELECT Col3, Col1, Col2
FROM Table2
GROUP BY Col3, Col1, Col2) tab2
ON tab2.Col2 = tab1.Col2 AND tab2.Col1 = tab1.Col1
At the moment for the rows in Table1 which do not exist in Table2 I return a row where Col3 is Null. As I am grouping data based on Col3, it would be good if I could somehow get the value of Col3 instead of Null.....
Is this possible??
So I am trying to return every possible combination of col1 and col2, per value of col3. The problem is when col3 does not contain a particular combination of col1,col2 I am getting nulls for col3...

Assuming Col3 is some kind of category, and is a primary key of a category table, you might do this:
select Category.Col3,
tab1.Col1,
tab1.Col2,
sum (tab2.YourAggregate) SumOfSomething
-- Take all categories
from Category
-- Cartesian product with Tabl1
cross join Table1 tab1
-- Find matching records in Table2, if they exist
left join Table2 tab2
on Category.Col3 = Tab2.Col3
and Tab1.Col1 = Tab2.Col1
and Tab1.Col2 = Tab2.Col2
group by Category.Col3,
tab1.Col1,
tab1.Col2
Cross join produces Cartesian product of tables involved, retrieving Col3 which might not be found in Table2.

A LEFT JOIN will produce nulls in the right table where no match could be found for Col1 and Col2 in the left table. This is the expected behavior.
If you need help writing a different query, you'll have to post your data structures and some sample data to play with.

Just switch your tables (or use right join):
SELECT tab2.Col3, tab2.Col1, tab2.Col2 FROM
(SELECT distinct Col3, Col1, Col2 FROM Table2) tab2
LEFT JOIN
(SELECT distinct Col1,Col2 FROM Table1) tab1
ON tab2.Col2 = tab1.Col2 AND tab2.Col1 = tab1.Col1

Related

Using column names and count togetger

I am new to SQL.
I am currently trying to write a query where i would like to list down all the details in my tables. I am using joins to get the together and everything is working fine. Where i get stuck is when i try to use count with my other columns. The issue is that the count i am referring to is a text field and as per that table the same id appears multiple times and i want to get the count from my query. My query looks like this
select col1, col2, col3, count(col4)
from table1 c
left join table2 a on c.id = a.id
however this does not work. I would appreciate any leads.
Use and study on group by. Your code should be something like below.
select col1, col2, col3, count(col4)
from table1 c
left join table2 a on c.id = a.id
group by col1, col2, col3
You need to add group by clause
select col1, col2, col3, count(col4)
from table1 c
left join table2 a on c.id = a.id
group by col1, col2, col3

In SQL can I Perform Logic on Multiple Columns, which are SELECT Statements?

I am trying to accomplish the following, and I am not sure if it is possible. I have a SELECT Statement that contains an inner SELECT for two of the table columns like so:
SELECT
col1,
col2,
(SELECT SUM(col1)
FROM table2)
AS FirstResultToAdd,
(SELECT SUM(col2)
FROM table3)
AS SecondResultToAdd,
FROM Table1
So my question is: Is it possible to perform a calculation, such as doing a SUM of "FirstResultToAdd" and "SecondResultToAdd, and returning that as a single column result on "Table1"? Also to keep in mind, I have excluded any joins of the tables to keep the example simple.
I believe you want to perform some logic on the result of Sub-query
To add the two sub-query result
SELECT col1,
col2,
(SELECT col1
FROM table2)
AS FirstResultToAdd,
(SELECT col2
FROM table3)
AS SecondResultToAdd,
(SELECT col1
FROM table2)
+
(SELECT col2
FROM table3)
AS total
FROM table1
To make the query more readable you can make the original query as Sub-Select and perform the logic in Outer query
just nest one more time...
select col1, col2, sum( FirstResultToAdd )
from (
SELECT
col1,
col2,
(SELECT col1
FROM table2)
AS FirstResultToAdd,
(SELECT col2
FROM table3)
AS SecondResultToAdd,
FROM Table1
)
Edit: Fixed Group By
Try this:
Select A.Col1,
A.Col2,
(B.Col3 + C.Col4)
From(
(Select Col1,
Col2
From [Table1]) A
Inner join (Select Sum(Col3) AS Col3
From [Table2]) B on 1 = 1
Inner join (Select Sum(Col4) AS Col4
From [Table3]) C on 1 = 1
)
Group By A.Col1,
A.Col2,
B.Col3,
C.Col4

copy a table into a new table and add a new column on SQL server 2008

I need to copy a table into a new table on SQL server 2008.
Also, add a new column into the new table.
The values of the new column depends on the compare result between the new table and another table.
Example,
Table1:
col1 col2 col3
abc 346 6546
hth 549 974
Expected Table1_new:
col1 col2 col3 col4
abc 346 6546 1
hth 549 974 0
Table2:
col1
abc
sfsdf
If Table2's col1 appear in Table1 col1, mark col4 as 1 in Table1_new, else mark as 0.
The code does not work
SELECT *,
(
SELECT 1 as col4
FROM Table2 as a
INNER JOIN Table1 as b
on b.col1 = a.col1
SELECT 0 as col4
FROM Table2 as a
INNER JOIN Table1 as b
on b.col1 <> a.col1 # I do not know how to do this !!!
)
INTO table1_new
FROM table1
Any help would be appreciated.
You could use an outer join:
SELECT table1.col1, col2, col3,
CASE WHEN table2.col1 IS NULL THEN 0 ELSE 1 END AS col4
INTO table1_new
FROM table1
LEFT OUTER JOIN table2 ON table1.col1 = table2.col1
You can do this in several ways. The following uses an exists clause in a case statement:
insert into table1_new(col1, col2, col3, col4)
select col1, col2, col3,
(case when exists (select 1 from table2 t2 where t2.col1 = t1.col1)
then 1 else 0
end)
from table1 t1;
You can also do this with a left outer join, but you run the risk of duplicates if t2 has duplicates.
INSERT INTO T2
SELECT COL1,COL2,COL3, (COL1+COL2) FROM T1
Note that instead of the (COL1+COL2) section you could run other expressions or possibly even a function.
Try something like this using CASE
SELECT
CASE
WHEN b.col1 = a.col1 THEN 1
ELSE 0
END as col4
FROM Table1 as a
LEFT JOIN Table2 as b
on b.col1 = a.col1
EDIT: Table1 should be the left table as mentioned in #Muerniks answer.
In addition to what the others already suggested: If you can't solve the problem in one step, try to make smaller steps. E.g. first initialize Table1.col4 with zero:
INSERT INTO Table1_new (col1,col2,col3,col4)
SELECT col1,col2,col3,0
FROM Table1
After that you will only need to identify the records which have matching partners in Table2 which is a classical inner join:
UPDATE t1 SET col4=1
FROM Table1_new t1
JOIN Table2 t2 ON t2.col1=t1.col1

Records difference in three tables - MS Access

I have three tables Tab1, Tab2 and Tab3 with almost same structre (in MS Access). But Tab2 and Tab3 have a few more columns than Tab1.
Tab2 and Tab3 are exactly same structure. Following are the joining keys
col1
col2
col3
Basically Tab1 records should tally with Tab2 and Tab3 together.
If I need to get the missing records in Tab2 and Tab3 when compare to Tab1 what could be the efficient way
Appreciate your response
If you only care about the keys, here is a good approach:
select col1, sum(isTab1) as numTab1, sum(isTab2) as numTab2, sum(isTab3) as numTab3
from ((select col1 as col, 1 as isTab1, 0 as isTab2, 0 as isTab3 from tab1
) union all
(select col2, 0 as isTab1, 1 as isTab2, 0 as isTab3 from tab2
) union all
(select col3, 0 as isTab1, 0 as isTab2, 1 as isTab3 from tab3
)
) t
group by col
having sum(isTab1)*sum(isTab2)*sum(isTab3) <> 1
This returns each of the key values and tells you which tables they are in and not in, for keys that are not in all three tables. As a bonus, this will also tell you if any of the tables have duplicate keys.
usually you would SELECT FROM tab1 LEFT JOINing the tab2 and tab3 LEFT JOINed together. That way you will get ALL records from tab1. When there are some missing records in tab2 and tab3 there will be nulls. You can check for nulls in the WHERE clause
So, the query would look similar to this one (please note the brackets - it is a requirement for ms-access):
SELECT * FROM
tab1 LEFT JOIN (tab2 LEFT JOIN tab3 ON tab2.col1 = tab3.col1 AND tab2.col2 = tab3.col2)
ON tab1.col1 = tab2.col1 AND tab1.col2 = tab2.col2
WHERE tab2.col1 Is Null;

Check for existing row before doing insert

Table1 columns:
clinic_code, schedule_date, schedule_time, source_id
Table2 columns:
clinic_code, schedule_date, schedule_time
There is a stored procedure that does:
1. Delete all records in Table1 where clinic_code='ABC' AND schedule_date=xyz
2. INSERT all records from table2 where table2.clinic_code='ABC' AND table2.schedule_date=xyz into table1.
I want to make a change in step 2.
*2. INSERT all records from table2 where table2.clinic_code='ABC' AND table2.schedule_date=xyz, but don't overwrite those rows in table1 where source_id=2.
Here's the original insert statement in step 2:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
Table names, and additional columns have been left out, if it would be helpful, I can put the exact number of columns.
I'm not sure I follow completely, because if you're inserting the rows into table1, table1.col3 won't have a value for those rows yet. If you just want to avoid having table1.col3 = 2, you could use a where clause like this:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
WHERE table2.col3 <> 2
Which would avoid inserting the value 2 into table1.col3, since table2.col3 is where you're pulling that from. If I'm missing the point here let me know, but that should do it.
EDIT - given that you've said the records between table1 and table2 are similar, and assuming there's a column you could join on between the two tables, you could do something like this:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
LEFT OUTER JOIN table1 t1 ON tl.colX = table2.colX
WHERE table1.col3 <> 2
The idea being that you've now included table1 in your SELECT and as such can also include it in your WHERE clause. (Forgive me if the aliasing syntax is off for other SQL flavors, I'm mostly experienced in T-SQL.)
Well I don't know which SQL you are using so here is a standard SQL script:
BEGIN TRANSACTION ;
IF NOT EXISTS ( SELECT * FROM dbo.table1 WHERE col3 = 2 )
BEGIN ;
...your insert goes here
END ;
COMMIT ;