What's the difference between these joins? - tsql

What's the difference between
SELECT COUNT(*)
FROM TOOL T
LEFT OUTER JOIN PREVENT_USE P ON T.ID = P.TOOL_ID
WHERE
P.ID IS NULL
and
SELECT COUNT(*)
FROM TOOL T
LEFT OUTER JOIN PREVENT_USE P ON T.ID = P.TOOL_ID AND P.ID IS NULL
?

The bottom query is equivalent to
SELECT COUNT(*)
FROM TOOL T
since it is not limiting the result set but rather producing a joined table with a lot of null fields for the right part of the join.
The first query is a left anti join.

Related

postgres error 42803 with subquery and group by

Hi all postgres developer,
below code can run success
select p.* from
(select p.*, count(distinct p1.id) n from TMB p
left join TMB p1 on p.id = p1.pid
left join TUR u on p.id = any(u.jks)
group by p.id) p
join TUR u on u.id = p.uid
but, below code with error message
[42803] ERROR: column "p.xxxx" must appear in the GROUP BY clause or be used in an aggregate function
select p.* from
(select p.*, count(distinct p1.id) n from (select * from TMB) p
left join TMB p1 on p.id = p1.pid
left join TUR u on p.id = any(u.jks)
group by p.id) p
join TUR u on u.id = p.uid
I want to do some where filter on TMB table before left join, so I think can speed up left join.
I think (select * from TMB) is a subquery equal as TMB. I can not understand why this error message. anyone can tell me detail?
The difference is that without the subquery, PostgreSQL can deduce that id is the primary key of tmb, so you need not add all columns of tmb to the GROUP BY clause. With the subquery, PostgreSQL cannot make that deduction, so you have to add all columns.

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.

Why does not adding distinct in this query produce duplicate rows?

This query was taken from a Rails application log...I'm trying to edit a massive postgresql statement I didn't write....If I don't add a distinct keyword after the SELECT, 2 duplicate rows appear for each braintree account. Why is this and is there another way to avoid having to use the distinct to avoid duplicates?
EDIT: I understand what distinct is supposed to do, the reason I'm asking is that it doesn't generate duplicates for other toy lines. By other toy lines, this query is building a "table" for a particular toy id (this specific example toys.id = 12). How do I figure out where the duplicate rows are being generated?
SELECT accounts.braintree_account_id as braintree_account_id,
accounts.braintree_account_id as braintree_account_id, format('%s %s', addresses.first_name,
addresses.last_name) as shipping_address_full_name,
users.email as email, addresses.line_1 as shipping_address_line_1,
addresses.line_2 as shipping_address_line_2, addresses.city as
shipping_address_city, addresses.state as shipping_address_state,
addresses.zip as shipping_address_zip_code, addresses.country
as shipping_address_country, CASE WHEN xy_shirt IS NULL THEN '' ELSE xy_shirt END, plans.name as plan_name, toys.sku as sku, to_char(accounts.created_at, 'MM/DD/YYYY HH24:MM:SS') as
account_created_at,
to_char(accounts.next_assessment_at, 'MM/DD/YYYY HH24:MM:SS') as account_next_assessment_at,
accounts.account_status as account_status FROM \"accounts\" INNER JOIN \"addresses\" ON
\"addresses\".\"id\" = \"accounts\".\"shipping_address_id\" AND \"addresses\".\"type\" IN
('ShippingAddress') LEFT OUTER JOIN shipping_methods ON
shipping_methods.account_id = accounts.id LEFT OUTER JOIN plans ON
accounts.plan_id = plans.id
LEFT OUTER JOIN users ON
accounts.user_id = users.id LEFT OUTER JOIN toys ON plans.toy_id = toys.id
LEFT OUTER JOIN account_variations ON accounts.id =
account_variations.account_id LEFT OUTER JOIN variations ON
account_variations.variation_id = variations.id
LEFT OUTER JOIN
choice_value_variations ON variations.id =
choice_value_variations.variation_id
LEFT OUTER JOIN choice_values ON
choice_value_variations.choice_value_id = choice_values.id LEFT OUTER
JOIN choice_types ON choice_values.choice_type_id = choice_types.id
LEFT
OUTER JOIN choice_type_toys ON choice_type_toys.toy_id = toys.id
AND choice_type_toys.choice_type_id = choice_types.id
LEFT OUTER JOIN
(SELECT * FROM crosstab('SELECT accounts.id, choice_types.id,
choice_values.presentation FROM accounts\n
LEFT JOIN account_variations ON
accounts.id=account_variations.account_id\n
LEFT JOIN variations ON account_variations.variation_id=variations.id\n
LEFT JOIN choice_value_variations ON
variations.id=choice_value_variations.variation_id\n
LEFT JOIN choice_values ON
choice_value_variations.choice_value_id=choice_values.id\n
LEFT JOIN choice_types ON choice_values.choice_type_id=choice_types.id
ORDER BY 1,2',\n 'select distinct choice_types.id
from choice_types JOIN choice_values ON choice_values.choice_type_id =
choice_types.id JOIN choice_value_variations ON
choice_value_variations.choice_value_id = choice_values.id JOIN
variations ON choice_value_variations.variation_id = variations.id JOIN choice_type_toys ON choice_type_toys.choice_type_id = choice_types.id JOIN toys ON toys.id = choice_type_toys.toy_id
where toys.id=12 ORDER
BY choice_types.id ASC')\n
AS (account_id int, xy_shirt
VARCHAR)) account_variation_view\n ON
accounts.id=account_variation_view.account_id WHERE
\"accounts\".\"account_status\" = 'active' AND
\"addresses\".\"flagged_invalid_at\" IS NULL AND \"toys\".\"id\" = 12
AND (NOT EXISTS (SELECT \"account_skipped_months\".* FROM
\"account_skipped_months\" WHERE
\"account_skipped_months\".\"month_year\" = 'JUL2016' AND
(account_skipped_months.account_id = accounts.id)))"
The purpose of using DISTINCT in a SELECT statement is to eliminate duplicate rows.

Left Join Is Not Doing What I expect

Totally confused and I have been working at this for 2 hours
I thought restriction on the left side of the join are honored
On this query I am getting [docSVsys].[visibility] 1 and <> 1
I thought this would restrict [docSVsys].[visibility] to 1
select top 1000
[docSVsys].[sID], [docSVsys].[visibility]
,[Table].[sID],[Table].[enumID],[Table].[valueID]
from [docSVsys] with (nolock)
left Join [DocMVenum1] as [Table] with (nolock)
on [docSVsys].[visibility] in (1)
and [Table].[sID] = [docSVsys].[sID]
and [Table].[enumID] = '140'
and [Table].[valueID] in (1,7)
This works
select top 1000
[docSVsys].[sID], [docSVsys].[visibility]
,[Table].[sID],[Table].[enumID],[Table].[valueID]
from [docSVsys] with (nolock)
left Join [DocMVenum1] as [Table] with (nolock)
on [Table].[sID] = [docSVsys].[sID]
and [Table].[enumID] = '140'
and [Table].[valueID] in (1,7)
where [docSVsys].[visibility] in (1)
I am just having a really off day as I had it in my mind the left side honored the join
SELECT *
FROM A
LEFT JOIN B ON Condition
is equivalent to
SELECT *
FROM A
CROSS JOIN B
WHERE Condition
UNION ALL
SELECT A.*, NULL AS B
FROM A
WHERE NOT EXISTS (SELECT * FROM B WHERE Condition)
Some rough pseudo-code...
Note, that all rows from A get through. It's just that the columns from B can be NULL if the join fails for some particular row of A.
Put the filter on docSVsys into the WHERE clause.
LEFT JOINs preserve all rows from the left (first) table, no matter what. The condition in the ON clause is only for matching which rows from the right/second table should be paired with rows from the left/first table.
If you want to exclude some rows from the firs table, use the WHERE clause:
select top 1000
[docSVsys].[sID], [docSVsys].[visibility]
,[Table].[sID],[Table].[enumID],[Table].[valueID]
from [docSVsys] with (nolock)
left Join [DocMVenum1] as [Table] with (nolock)
on [Table].[sID] = [docSVsys].[sID]
and [Table].[enumID] = '140'
and [Table].[valueID] in (1,7)
where [docSVsys].[visibility] in (1)

Is it possible to JOIN with a var from a LEFT JOIN without destrorying rows?

My code generates a large query. A simple version is
SELECT * FROM main_table as mt
JOIN user_data AS ud ON mt.user_id=ud.id
LEFT JOIN ban_Status AS bs ON ud.status_id=bs.id
JOIN AnotherTable ON bs.data=AnotherTable.id
NOTE: This code is untested.
When i remove the last join i get results. I can also change it to left join but that would be wrong. If ud.status is not null i would like a join as i always do when i do a select query from ban_Status. How do i fix this? must i write left join on every table if i left join the parent table? would that not give me side effects?
I am using sqlite ATM but will switch to tsql
Use the LEFT JOIN, but in your WHERE clause specify that either both ud.status_id is null and AnotherTable.id is null or neither is null.
SELECT * FROM main_table as mt
JOIN user_data AS ud ON mt.user_id=ud.id
LEFT JOIN ban_Status AS bs ON ud.status_id=bs.id
LEFT JOIN AnotherTable ON bs.data=AnotherTable.id
WHERE (ud.status_id is null and AnotherTable.id is null)
or (ui.status_id is not null and AnotherTable.id is not null)
That will keep you from selecting any records that have a ban_Status but don't have the additional data from the other table.