sql union displays duplicates - sql

image of what I want
I have tried the join on x or y and it didn't work, even the group by didn't work.
What almost gave me the result is the query below
SELECT A.Id ,A.AccNo ,A.Name ,B.Id ,B.AccNo1 ,B.AccNo2 ,B.Name
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo1
union
SELECT A.Id ,A.AccNo ,A.Name ,B.Id, B.AccNo1, B.AccNo2, B.Name,
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo2
After getting the query correct I want to show only the exceptions where there was no link between the tables and its kind of difficult if the T1.ID is repeated

You seem to want a left join:
select t1.*, t2.*
from table1 t1 left join
table2 t2
on t1.id in (t2.accno1, t2.accno2);

Try:
SELECT A.Id ,A.AccNo ,A.Name ,B.Id ,B.AccNo1 ,B.AccNo2 ,B.Name
from Table1 as A
left outer join Table2 as B
ON A.AccNo = (CASE WHEN A.AccNo = B.AccNo1 THEN B.AccNo1 ELSE B.AccNo2 END)

You may nest your original query, and then use max aggregate function with grouping :
SELECT Id ,AccNo ,Name, max(Id2) as Id2, max(Name2) as Name2,
max(AccNo1) as AccNo1, max(AccNo2) as AccNo2
FROM
(
SELECT A.Id ,A.AccNo ,A.Name ,B.Id Id2 ,B.AccNo1 ,B.AccNo2 ,B.Name Name2
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo1
union
SELECT A.Id ,A.AccNo ,A.Name ,B.Id Id2, B.AccNo1, B.AccNo2, B.Name Name2
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo2
) q
GROUP BY Id ,AccNo ,Name;
SQL Fiddle Demo

Do a LEFT JOIN to return the table1 values along with matching table2 values (where t2.accno2 = t1.accno):
select t1.*, t2.*
from table1 t1
left join table2 t2
on t1.accno = t2.accno2
Or, perhaps you want table2 values for matching accno1's as well?
select t1.*, t2.*
from table1 t1
left join table2 t2
on t1.accno in (t2.accno1, t2.accno2)

It this way to resolve:
SELECT
t1.id,
t1.accno,
t1.name,
(
SELECT DISTINCT
id
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
name
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
accno1
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
accno2
FROM
table2
WHERE
accno2 = t1.accno
) FROM
table1 t1
LEFT JOIN table2 t2 ON t1.accno = t2.accno1 OR t1.id = t2.id

Related

How to Group By all fields nested tables in a Left Join query in BigQuery?

I have about 10 tables that I make one big nested tables by rounds with the following query:
R1 AS(
SELECT ANY_VALUE(Table1).*, ARRAY_AGG(( SELECT AS STRUCT Table2.* EXCEPT(ID))) AS Table2
FROM Table1 LEFT JOIN Table2 USING(ID)
GROUP BY Table1.ID),
R2 AS(
SELECT ANY_VALUE(R1).*, ARRAY_AGG(( SELECT AS STRUCT Table3.* EXCEPT(ID))) AS Table3
FROM R1 LEFT JOIN Table3 USING(ID)
GROUP BY R1.ID),
...
SELECT ANY_VALUE(R9).*, ARRAY_AGG(( SELECT AS STRUCT Table10.* EXCEPT(ID))) AS Table10
FROM R9 LEFT JOIN Table10 USING(ID)
The thing is that for example in my first table I can have two records with the same ID but some other fields will be different and I want to consider them as two distinct records and thus group by all the fields of the table while I join.
Then I want to do the same with all the "sub-table" (the R tables in the query), so I will able to group by all the fields of the nested tables.
How can I do it easily ?
I tried GROUP BY Table1.* but it doesn't work...
Thank you in advance
Try to_json_string:
...
FROM Table1 t1
...
GROUP BY to_json_string(t1)
You seem to want something like this:
select *
from table1 t1 left join
(select t2.*
from table2 t2
where true
qualify row_number() over (partition by t2.id order by t2.id) = 0
) t2
using (id)
This uses qualify instead of group by to fetch one row.
If you don't want all rows from from table1, you can whittle them down as well:
select *
from (select t1.*
from table1 t1
where true
qualify row_number() over (partition by id, col1, col2 order by id) = 1
) t1 left join
(select t2.*
from table2 t2
where true
qualify row_number() over (partition by t2.id order by t2.id) = 0
) t2
using (id)
How to Group By all fields ...?
I tried GROUP BY Table1.* but it doesn't work...
Consider below example
SELECT ANY_VALUE(t1).*,
ARRAY_AGG(( SELECT AS STRUCT t2.* EXCEPT(ID))) AS Table2
FROM Table1 t1 LEFT JOIN Table2 t2 USING(ID)
GROUP BY FORMAT('%t', t1)

Using update with Left Join and cross join BigQuery

I have a followup question on my already posted question.
Using update with Left Join BigQuery
I amt trying to achieve the same result but also adding Cross Join in it.
update Table1
set ColumnTest = ifnull(b.value, 'no run')
From left join
(select distinct h.eventinfo.eventcategory as ID,value
FROM Table2
cross join (hits)h )
where Table1.ID= Table2.ID
I have 2 tables Table1 and Table2
I want to update Table1.ColumnTest with Table2.Value
where Table1.ID= Table2.hits.eventInfo.eventCategory (Unnest Table2)
and if Table1.ID <> Table2.hits.eventInfo.eventCategory then update Table1.ColumnTest with 'no run'
Thanks for you help!!
Try below
UPDATE `table1` t1
SET ColumnTest = IFNULL(t2.value, 'no run')
FROM (
SELECT id, value
FROM `table1`
LEFT JOIN (
SELECT hit.eventInfo.eventCategory AS id, value
FROM `table2`
CROSS JOIN UNNEST (hits) AS hit
)
USING(id)
) t2
WHERE t1.ID = t2.ID

How to join 2 tables without creating duplicated rows of records in SQL

I have 2 tables (Table 1 and Table 2) which I would like to join and get the records of ALL dates..
I tried left join on Table1.productid = Table2.productid but it does not give me the expected output that I want..
Does anyone have experience in solving this type of join in SQL?
Use UNION ALL
SELECT
t1.Date_id,
t1.Product_id,
t1.Clicks,
0 AS Sales
FROM table1 t1
UNION ALL
SELECT
t2.Date_id,
t2.Product_id,
0 AS Clicks,
t2.Sales
FROM table2 t2
Yes you can do a full outer join to get the output as follows
select case when a.date_id is null then b.date_id end as date_id
,case when a.product_id is null then b.product_id else a.product_id end as product_id
,case when a.clicks is null then 0 else a.clicks end as clicks
,case when b.sales is null then 0 else b.sales end as sales
from table1 a
full outer join table2 b
on a.product_id=b.product_id
and a.date_id=b.date_id
Something like this may work:
INSERT INTO Your_new_table3(DateId, ProductId, Clicks, Sales)
SELECT * FROM Table1
UNION ALL
SELECT * FROM Table2;
You can use Outer Apply . Read Microsoft doc about this.
SELECT
t1.Date_id,
t1.Product_id,
t1.Click,
t2.Sales
FROM
table1 t1
OUTER APPLY
(
SELECT TOP 1 *
FROM table2 t2
WHERE t2.productid = t1.productid
) t2
OR use Group by statement :
SELECT DISTINCT
String_agg(t1.Date_id,'-'),
t1.Product_id,
t1.Click,
t2.Sales
FROM table1 t1
LEFT JOIN table2 t2 ON t2.productid = t1.productid
Group by t1.Product_id,
t1.Click,
t2.Sales
OR sue Distinct statement :
SELECT DISTINCT
t1.Date_id,
t1.Product_id,
t1.Click,
t2.Sales
FROM table1 t1
LEFT JOIN table2 t2 ON t2.productid = t1.productid

SQL Query, how to get data from two tables

Table 1:
ID (unqiue), Name, Address
Table 2:
RecordId, ID (key of table 1), Child name
In one query, I want to retrieve all rows of Table 1 with one additional column which will be the count of all record in table 2 from ID (that is number of children for each ID in table 1). Can't figure out how to format a query to retrieve this data.
Simply Join and apply count
select T1.*, COUNT(T2.RECORDID)AS T2COUNT from Table1 T1
INNER JOIN TABLE2 T2 ON T1.ID= T2.ID
--LEFT JOIN TABLE2 T2 ON T1.ID= T2.ID --if you need 0 child records (from commets by #Cha)
GROUP BY T1.ID , T1.Name, T1.Address
The correct way of doing this will be with a OUTER JOIN:
SELECT a.ID, a.Name, a.Address, b.cnt
FROM Table1 a
LEFT OUTER JOIN
(SELECT ID, count(*) cnt from Table2 GROUP BY ID) b
ON a.ID = b.ID
The incorrect way will be with a help of a correlated sub-query:
SELECT a.ID, a.Name, a.Address,
(SELECT count(*) FROM Table2 b WHERE b.ID = a.ID) as cnt
FROM Table1 a
Here is a discussion about correlated subqueries vs OUTER JOINs, if you are interested
Group by table1 fields and count total records in table2:
here T1 alias of table1 and T2 alias of table2.
select T1.ID, T1.Name, T1.Address, count(T2.ID) as total_records
from table1 as T1
left outer join table2 as T2 on T2.ID=T1.ID
group by T1.ID, T1.Name, T1.Address

Join 2 tables on different columns based on condition

I have two tables, tbl and tbl2 I have to join. Columns of tbl are irrelevant. Here is the tructure of tbl2:
CREATE TABLE tbl2 (
a VARCHAR(10)
, b VARCHAR(10)
, c VARCHAR(10)
, d VARCHAR(10)
, e VARCHAR(10)
);
What I need to do is apply the following join:
if there are several rows with the same a, b and c LEFT JOIN them on a, b, c and d.
else if there are several rows with the same a and b and they are not in the set mentioned above LEFT JOIN on a, b and c
else LEFT JOIN remaining rows from tbl2 on a and b.
I have been thinking what is the best way to achieve the following. tbl2 can be modified since it is only used for the purpose of this query.
Do you have any ideas what is the most efficient way of achieving this?
EDIT:
By 'having the same a, b and c' I meant something like this:
SELECT a, b, c FROM tbl2 GROUP BY a, b ,c HAVING COUNT(*) > 1
WITH tab_a AS
(
SELECT t2.a
, t2.b
, t2.c
, t2.d
, t2.e
, CASE WHEN t1.c = t2.c THEN 1 ELSE 0 END +
CASE WHEN t1.d = t2.d THEN 1 ELSE 0 END AS other_two
FROM tbl t1
LEFT JOIN tbl2 t2
ON t1.a = t2.a
AND t1.b = t2.b
)
SELECT a
, b
, c
, d
, e
FROM tab_a
WHERE other_two = (SELECT MAX(other_two) FROM tab_a);
put these three queries in if else condition. If you want them all then UNION these three.
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t1.d=t2.d)
where t2.a=t2.b and t2.b=t2.c;
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b and t1.c=t2.c )
where t2.a=t2.b and t2.b<>t2.c;
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b)
where t2.a<>t2.b and t2.b<>t2.c;
or try this:
select *
from tbl t1 left outer join tbl2 t2
on (
(t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t1.d=t2.d and t2.a=t2.b and t2.b=t2.c)
or
(t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t2.a=t2.b and t2.b<>t2.c)
or
(t1.a=t2.a and t1.b=t2.b and t2.a<>t2.b and t2.b<>t2.c) );