SQL: Joining tables using wildcards - postgresql

When I join 2 tables
select t1.col1, t1.col2, t2.col3
from t1
left join t2
on t1.col2=t2.col3
Then I don't get any duplicate rows. However, when I try joining
tables using wildcards:
select t1.col1, t1.col2, t2.col3
from t1
left join t2
on t1.col2 like '%'||t2.col3
Then I'll get duplicate values. I saw this post that I think is
getting me somewhere but I couldn't really understand the solution.
Joining 2 Tables using a wildcard
It says I can use exists to get rid of duplicate values. I also
don't really understand his query. Here is the query in the other
post:
select *
from tableA a
where exists (select 1 from tableB b where a.id like '%' + b.id + '%');
What does the select 1 from tableB do?
I'm using PostgreSQL
This is what I've tried even though I don't understand it and still gives me duplicates:
select t1.col1,t1.col2,t2.col3
from t1
left join t2
on t1.col2 like '%'||t2.col3
where exists (select 1 from t2 where t1.col2 like '%'||t2.col3)

Use the DISTINCT clause:
SELECT DISTINCT t1.col1, t1.col2, t2.col3
FROM t1
LEFT JOIN t2 ON t1.col2 LIKE '%'||t2.col3;

Related

select count from both tables using join in postgesql

how to find number of records in both table using join.
i have two tables table1 and table2 with same structure.
table1
id
item
1
A
1
B
1
C
2
A
2
B
table2
id
item
1
A
1
B
2
A
2
B
2
C
2
D
Output should be like this.
id
table1.itemcount
table2.itemcount
1
3
2
2
2
4
SELECT DISTINCT id, (
SELECT COUNT(*) FROM table1 AS table1_2 WHERE table1_2.id=table1.id
) AS "table1.itemcount", (
SELECT COUNT(*) FROM table2 AS table2_2 WHERE table2_2.id=table1.id
) AS "table2.itemcount"
FROM table1;
Assuming that each id is guaranteed to exist in both tables, the following would work
select
t1.id,
count(distinct t1.item) t1count,
count(distinct t2.item) t2count
from t1
join t2 on t1.id = t2.id
group by 1;
But if that is not guaranteed then we'll have to use full outer join to get unique ids from both tables
select
coalesce(t1.id, t2.id) id,
count(distinct t1.item) t1count,
count(distinct t2.item) t2count
from t1
full outer join t2 on t1.id = t2.id
group by 1;
We're using coalesce here as well for id because if it only exists in t2, t1.id would result in null.
#DeeStark's answer also works if ids are guaranteed to be in both tables but it's quite inefficient because count is essentially run twice for every distinct id in the table. Here's the fiddle where you can test out different approaches. I've prefixed each query with explain which shows the cost
Hope this helps

Postgresql query many to many relationship with left join and use where clouse not show data

I have three table, table_1 (id), table_2(id), table_pivot(tbl1_id, tbl2_id). When I use query like this:
select *
from public.table_1 t1
left join public.table_pivot tp on tp.tbl1_id = t1.id and tp.user_id = 1
left join public.table_2 t2 on t2.id = tp.tbl2_id;
Data from table_1 is show. But when I use where condition. Like this:
select *
from public.table_1 t1
left join public.table_pivot tp on tp.tbl1_id = t1.id
left join public.table_2 t2 on t2.id = tp.tbl2_id
where tp.user_id = 1;
Data from table_1 not show.
I hope advance can help explain why?
Thanks.
Including a where clause on an outer joined table, effectively converts the join into an inner join. If there are no matching values in table_pivot, then
you will get no results at all. This is standard sql.

If transaction_id is not null join on transaction_id else join on user id - in same join?

I would like to do a single left join from table a onto table b on transaction_id
select a.*, b.*
from tablea a
left join tableb b on b.transaction_id = a.transaction_id
However, there are cases where transaction id on either table is missing, in which case I would like to fall back onto joining on a.user_id = b.user_id. If user_id is also missing then fine, I still want to keep all records from a.
Is there a way I can tell postgres to try joining on one field and if it's missing on either table to then try joining on another field?
Is there a way to do this?
Add a 2nd join to tableb with the condition that the 1st join did not match:
select a.*,
coalesce(b1.col1, b2.col1), coalesce(b1.col2, b2.col2), .....
from tablea a
left join tableb b1 on b1.transaction_id = a.transaction_id
left join tableb b2 on b2.user_id = a.user_id and b1.transaction_id is null

I want to join 3 tables and select 1 coulmn from each table

I have tried using join as follows but it is not working
SELECT distinct(udf.FIELD_NAME),fun.FUNCTION_ID,mo.MODULE AS PRODUCT_MODULE FROM TABLE1 udf
JOIN TABLE2 mo
ON udf.PRODUCT_CODE = mo.PRODUCT_CODE
JOIN TABLE3 fun
ON udf.FIELD_NAME = fun.FIELD_NAME
where (udf.product_code in (select mo.product_code from TABLE2 mo))AND(udf.FIELD_NAME like '%UDF%')AND(udf.FIELD_NAME IN(SELECT fun.FIELD_NAME FROM TABLE3 fun));
I want all the where conditions mentioned here to work
There are some statements in your WHERE clause that mimic the join condition. If you do a join like this
JOIN TABLE2 mo
ON udf.PRODUCT_CODE = mo.PRODUCT_CODE
then there is no need to add the WHERE clause
where (udf.product_code in (select mo.product_code from TABLE2 mo))
because those 2 do the same. Unless you have duplicate rows, the "DISTINCT" clause is not needed either. Your query can be rewritten as:
SELECT
udf.field_name,
fun.function_id,
mo.module AS product_module
FROM
table1 udf
JOIN table2 mo ON udf.product_code = mo.product_code
JOIN table3 fun ON udf.field_name = fun.field_name
WHERE
udf.field_name LIKE '%UDF%';

Join table variable vs join view

I have a stored procedure which is running quite slow. Therefore I want to extract some of the query in a separate view.
My code looks something like this:
DECLARE #tmpTable TABLE(..)
INSERT INTO #tmpTable (..) *query* (returns 3000 rows)
Select ... from table1
inner join table2
inner join table3
inner join #tmpTable
...
I then extract (copy-paste) the *query* and put it in a view - i.e. vView.
Doing this will then give me a different result:
Select ... from table1
inner join table2
inner join table3
inner join vView
...
Why? I can see that the vView and the #tmpTable both returns 3000 rows, so they should match (also did a except query to check).
Any comments would be much appriciated as I feel quite stuck with this..
EDITED:
This is the full query for getting the result (using #tmpTable or vView gives me different results, although the appear the same):
select dep.sid as depsid, dep.[name], COUNT(b.sid) as possiblelogins, count(ls.clientsid) as logins
from department dep
inner join relationship r on dep.sid=r.primarysid and r.relationshiptypeid=27 and r.validto is null
inner join [user] u on r.secondarysid=u.sid
inner join relationship r2 on u.sid=r2.secondarysid and r2.validto is null and r2.relationshiptypeid in (1,37)
inner join client c on r2.primarysid=c.sid
inner join ***#tmpTable or vView*** b on b.sid = c.sid
left outer join (select distinct clientsid from logonstatistics) as ls on b.sid=ls.clientsid
GROUP BY dep.sid, dep.[name],dep.isdepartment
HAVING dep.isdepartment=1
You maybe don't need the view/table if you change to this.
It joins on to client c and appears to be there only to JOIN onto logonstatistics
--remove inner join ***#tmpTable or vView*** b on b.sid = c.sid
--change JOIN
left outer join (select distinct clientsid from logonstatistics) as ls on c.sid=ls.clientsid
And change COUNT(b.sid) to COUNT(c.sid) in the SELECT clause
Otherwise, if you get different results you have two options I can see:
Table and view have different data. Have you run a line by line comparsion?
One has NULL, one has a value (especially for the sid column which will affect the JOIN)
Finally, when you says "different results" do you mean you get x2 or x3 rows? A different COUNT? What?