unexpected LEFT OUTER JOIN behaviour in SQLITE - sql

I have two tables in SQLITE
"port" is
ticker weight
abc 1
bcd 2
cde 3
"bench2" is
ticker weight
abc 3
bcd 2
cde 1
and Im trying to learn how to use an outer join in SQLITE. Starting with a LEFT OUTER JOIN as follows
SELECT * FROM port LEFT OUTER JOIN bench2 ON port.ticker = bench2.ticker;
I get the result
ticker weight ticker weight
abc 3 NULL NULL
bcd 2 bcd 2
when I'd expect to see
ticker weight weight
abc 1 3
bcd 2 2
cde 3 1
what am I doing wrong and how would I get the result I want?
Second question if possible - how could I get an additional row of
ticker weight weight
abc 1 3
bcd 2 2
cde 3 1
def NULL 3
in the result table if "bench2" had an extra row,
ticker weight
abc 3
bcd 2
cde 1
def 3
while port remained the same.

Reverse-engineering your result leads me to conclude that your data are different than you say. You appear to have this:
port:
ticker weight
abc 3
bcd 2
... (no other rows)
bench2:
ticker weight
bcd 2
... maybe other rows, but none having ticker = 'abc'
As for the columns, when you perform any join other than a NATURAL JOIN, there is one result column for each column in each of the joined tables, including when there are columns with the same name, and including columns appearing in the join condition. You can limit which of those columns appear in the final query result, and / or you can assign preferred aliases to them, by specifying in the select list which ones you want.

How about something like this?
SELECT table2.ticker,
table1.weight,
table2.weight
FROM table2
LEFT OUTER JOIN table1
ON table1.ticker = table2.ticker

Related

Join using 2 'alternative' columns from one table

I have 2 large tables like bellow in Teradata. I need to join them so that:
all records from Table A are kept - like A left join B
join is on A.client_id=B.client_id_1
but if B.client_id_1 is null, it can join on A.client_id=B.client_id_2
Table A
client_id
details_a
1
abc
2
def
3
ghi
4
jkl
Table B
client_id_1
client_id_2
details_b
1
null
123
null
2
456
3
3
789
The result should be like:
client_id
details_a
client_id_1
client_id_2
details_b
1
abc
1
null
123
2
def
null
2
456
3
ghi
3
3
789
4
jkl
null
null
null
The tables are large and the join is part of a larger script (other joins using Table B)
I tried something like
Table A LEFT JOIN Table B
ON (A.client_id = B.client_id_1 OR A.client_id = B.client_id_2)
But the result was product join that never finished.
I also want to avoid two left joins (on B.client_id_1 and on B.client_id_2) as it would result in having all columns from Table B twice. And the Table B is further used in following joins. Plus client_id=3 would have two records.
Any idea? And what is wrong with the JOIN using OR above?
Thanks, R.
You can use case statement:
Table A LEFT JOIN Table B
ON (A.client_id = case when B.client_id_1 is null then B.client_id_2 else B.client_id_1 end)
oR Coalesce:
Table A LEFT JOIN Table B
ON (A.client_id = Coalesce(B.client_id_1 ,B.client_id_2 ))
If B.client_id_1 is not null then Coalesce(B.client_id_1 ,B.client_id_2 ) will return B.client_id_1 but if it's null then the condition will return B.client_id_2 .

Join more than 2 tables with aggregate functions without FK and having same id in all tables

I have 3 tables
table 1
customerid customername
1 abc
2 bcd
3 cde
4 def
5 efg
table 2
Customerid customername salesqty saleprice
1 abc 10 30
3 cde 20 40
4 def 15 50
table 3
customerid customername growth
1 abc -10
2 bcd 100
3 cde -50
4 def 20
How I can join these tables using sum operator for salesqty, saleprice, growth & I have to get total customer in this table (which join I have to use) finally the table look like.
Customerid customername salesqty saleprice growth
1 abc x x x
2 bcd x x x
3 cde x x x
4 def x x x
5 efg x x x
You can create a query with left joins to display results as you have in your Table4. You can eventually change this query to append query to get a results into another table (in your case table4).
Select table1.customerid, table1.customername, table2.salesqty, table2.salesprice, table3.growth
From (table1 Left Join table2 On table1.customerid=table2.customerid) Left Join table3 On table1.customerid = table3.customerid;
However I do not know what you are trying to achieve, but it is a good practice to build relationships using PK to FK as that way you would be able to normalize your database and don't have to keep repeating columns in different tables.

Left join to a table where values do not exist (and are not NULLs)

EDIT (SOLVED): A cross join. One of those joins you never use until you need it. Thanks for the help
Left table: TS , single field with values [1,2,...,365].
Right table: PAYMENT with three fields (ID, TS, AMT)
For each ID, I want to see 365 records from a left join of TS on PAYMENT.
The problem is that "no value" is not the same as a NULL.
If PAYMENT.TS does not exist for a certain value (e.g. PAYMENT.TS=4), then there is no value to join on and the left join does not return a row #4.
I tried using NOT IN / NOT EXISTS as a condition, but this only treats the case where the right table has explicit NULLS and not the case where no value exists.
How can I proceed? Thanks!
(This is a DB2 system)
SELECT * FROM TS LEFT JOIN PAYMENT ON TS = PAYMENT.TS
TS TABLE:
| TS |
----------
1
2
...
365
PAYMENTS TABLE:
| ID | TS | PMT |
-----------------------------
1 1 70
1 2 20
1 5 10
2 3 200
EXPECTED RESULT:
| ID | TS | PMT |
-----------------------------
1 1 70
1 2 20
1 3
1 4
1 5 10
... ...
1 365
2 1
2 2
2 3 200
... ...
2 365
ACTUAL RESULT:
| ID | TS | PMT |
-----------------------------
1 1 70
1 2 20
1 5 10
2 3 200
You need to generate all the rows you want using a cross join and then use left join:
SELECT i.id, ts.ts. p.amt
FROM (SELECT DISTINCT ID FROM PAYMENT) i CROSS JOIN
TS LEFT JOIN
PAYMENT p
ON ts.TS = p.TS AND p.id = i.id;
This will return 365 rows for each id.
You have to join them matching the two common columns in each table. Preferably by the keys(foreign and primary).
Let's say TS table has this one column called 'NUMBERS' and its type is int. The table PAYMENT has the column ID, type of int also. Which means they may have common values. Thus, if you want to join two tables and get the common ones where the PAYMENT.ID exists in TS.NUMBERS then you should do:
SELECT * FROM TS LEFT JOIN PAYMENT ON TS.NUMBERS = PAYMENT.ID
I hope I've been clear.
Note: Also do not forget that if a column or more has the same name in both tables, you have to clarify from which table you want that column for instance if also PAYMENT table had the column named as NUMBERS, then:
SELECT PAYMENT.ID, TS.NUMBERS FROM TS LEFT JOIN PAYMENT ON TS.NUMBERS = PAYMENT.ID

merging two tables and adding additional column

I am using sql-server. I have two tables (simple snap shot below).
table hlds table bench
name country wgt name country wgt
abc us 30 abc us 40
mno uk 50 ppp fr 45
xyz us 20 xyz us 15
what I would like to do is calculate the differnces in the wgt columns and insert the results into another table, lets call it merge_tbl. The other thing I would like to do is in merge_tbl have a bit column where it is 1 if the company exists in the table hlds.
So I would like the result to look like below,
merge_tbl
name country wgt inHld
abc us -10 1
mno uk 50 1
xzy us 5 1
ppp fr -45 0
How do I go about doing this?
I think you need a FULL OUTER JOIN to get records from both tables. Then, you can use a INSERT INTO SELECT statement to do the insert:
INSERT INTO merge_tbl
SELECT COALESCE(h.name, b.name) AS name,
COALESCE(h.country, b.country) AS country,
COALESCE(h.wgt, 0) - COALESCE(b.wgt, 0) AS wgt,
CASE WHEN h.name IS NOT NULL THEN 1
ELSE 0
END AS inHld
FROM hlds AS h
FULL OUTER JOIN bench AS b ON h.name = b.name AND h.country = b.country
The ON clause of the JOIN operation depends on your actual requirements. I have made the assumption that records from hlds, bench tables match if both name and country fields are equal.
Demo here

Compare 2 tables in sql

I have two tables, A1 and A2. I want to compare these two tables. I tried inner join but it doesn't give the required result.
These are the data in these tables,
Table A1
No. Address
1 abc
1 abc
1 def
1 def
Table A2
No. Address
1 def
1 abc
1 abc
1 def
These two tables can only be joined by using No. column. So if I use INNER JOIN it gives 16 rows. I don't want that, I want only 4 rows to be displayed. This should be the output:
No. Address eq
1 abc #
1 abc *
1 abc #
1 abc #
Last column is displayed if address in A1 is equal to A2
Search for records that exist in A1 table but not in A2 table:
SELECT * FROM A1 WHERE NOT EXISTS (SELECT * FROM A2 WHERE A2.Id = A1.Id)
try to use case
select case when tablea1.address=tablea2.address then '*'
else '#' end as eq from tablea1 inner join tablea2 on tablea1.=tablea2.
hope it helps you.