how to update BigQuery table using struct column - sql

My Big Query table T1 is as below.
T1
A string,
B string,
C Record,
C.key string,
C.formula string,
D string
I want to update column D based on B and C, with query something like below.
update T1
set D = 'd1'
where B = 'b1' and C.formula = 'f1' ;
How to do that in BigQuery ?

Even simpler version
update T1 t
set D = 'd1'
where B = 'b1' and
'f1' in (select formula from t.C);

You don't have a record for C. You have an array of records. So, you can use unnest():
update T1
set D = 'd1'
where B = 'b1' and
exists (select 1
from unnest(T1.C) as c_el
where c_el.formula = 'f1'
);

Related

SQL query from extracted column

I have the following oracle sql query:
SELECT DISTINCT A, B, C, D
FROM my_table
WHERE (B IN (SELECT ID_X FROM table2))
This is fine because B is in table2.
Now I would like to query for column D which is not in table2 but can be mapped from my_table via D.
Table "my_table":
A
B
C
D
abc
def
ghi
jmk
Table "table2":
B
value
def
2
How can I first extract the value of column B if I only have the value of column D:
jmk -> def
And then use that value to extract my data from table2:
def -> 2
Use an inner join:
SELECT DISTINCT t1.*, t2.value
FROM my_table t1
INNER JOIN table2 t2
ON t2.ID_X = t1.B;
With your sample data:
WITH
tbl AS ( Select 'abc' "A", 'def' "B", 'ghi' "C", 'jmk' "D" From Dual ),
tbl_1 AS ( Select 'def' "B", 2 "VALUE" From Dual )
try this:
SELECT t.A, t.B, t.C, t.D, t1.VALUE "VALUE_OF_B"
FROM tbl t
LEFT JOIN tbl_1 t1 ON(t1.B = t.B)
WHERE t.D = 'jmk'
R e s u l t :
A B C D VALUE_OF_B
--- --- --- --- ----------
abc def ghi jmk 2
If there is no match of column B in tbl_1 you will get the row where VALUE_OF_B is null. If you put INNER instead of LEFT JOIN then, without the match, no rows will be selected. It's up to you to decide what kind of join to use...

Update a table column using a mapping table?

I have three tables: a, b, c. Table b is a mapping table for table a and table c. I am trying to update table a column = table c column.
When implementing the update, I receive an error:
[S0001][4104] The multi-part identifier could not be bound
UPDATE table_a
SET table_a.Sector = table_c.Sector
FROM table_a
INNER JOIN table_b
ON table_a.business_ID = cast(table_b.business_id as BIGINT)
INNER JOIN table_c
ON table_b.ACARA_SML_ID = table_c.ACARA_SML_ID
WHERE a.State = 'ABC';
Use UPDATE statement directly from SELECT clause :
UPDATE table_a SET table_a.Sector = C.Sector
FROM table_c C
WHERE EXISTS
( SELECT 1 FROM table_b B B.ACARA_SML_ID = C.ACARA_SML_ID AND
table_a.business_ID = CAST(B.business_id AS BIGINT)
) AND A.[STATE] = 'ABC'
In your WHERE clause you are using a.State, here a was not set as table alias for any of the table.
Can you try this query with correct table alias:
UPDATE A
SET Sector = C.Sector
FROM table_a A
INNER JOIN table_b B ON A.business_ID = CAST(B.business_id AS BIGINT)
INNER JOIN table_c C ON B.ACARA_SML_ID = C.ACARA_SML_ID
WHERE A.[STATE] = 'ABC';

How to find doubles in master-child table?

I need help with a query to find doubles. Let met explain the situation by example:
tableA (the master table) has a key field keyA with these values :
keyA
1
2
3
etc
tableB (the client table) has a foreign key field keyA and a value field, fieldB
keyA fieldB
1 a
1 b
2 a
2 b
3 a
3 c
4 a
4 b
4 c
etc
So, the values for fieldB in child table tableB are:
for tableA.keyA = 1 are: a and b
for tableA.keyA = 2 are: a and b
for tableA.keyA = 3 are: a and c
for tableA.keyA = 4 are: a, b and c
Now, given a value for keyA I need to find all records in tableA that have matching records in tableB for the field fieldB.
For example, if I search with keyA = 1 then
tableA.keyA = 2 is OK because both have same tableB.fieldB (a and b versus a and b)
tableA.keyA = 3 is not OK because both have not same tableB.fieldB (a and b versus a and c)
tableA.keyA = 4 is not OK because both have not same tableB.fieldB (a and b versus a, b and c)
I need a query that can give me this result. I hope someone can help me with this or can point me into the right direction.
Try this simple query , hope this will solve your problem
DECLARE #vkey int = 1
;WITH cte_test AS (
SELECT keyA,(SELECT ','+fieldb FROM tableB t1 WHERE t1.keyA = t.keyA FOR XML path('')) AS rslt
from tableB t
GROUP BY t.keyA)
SELECT t2.*
FROM cte_test t1
INNER JOIN cte_test t2 ON t1.[rslt] = t2.[rslt] AND t2.[keyA] <> t1.[keyA]
WHERE t1.[keyA] = #vkey
If there is no other item have the same combination , then there is no records in the result, otherwise it will return the matched items.
Assuming there are no duplicates, you can do this with a self-join and aggregation:
select c.keyA, c2.keyA
from (select c.*, count(*) over (partition by keyA) as numBs
from clientTable c
) c join
(select c.*, count(*) over (partition by keyA) as numBs
from clientTable c
) c2
on c2.fieldB = c.fieldB and
c2.keyA <> c.keyA and
c.keyA = 1 -- or whatever key you want to check
where c.numBs = c2.numBs
group by c.keyA, c2.keyA, c.numBs, c2.numBs
having count(*) = c.numBs;
The idea is to count the number of fieldB values for each keyA. These need to be equal (where c.numBs = c2.numBs) and to check that all match (having count(*) = c.numBs).

SQL Query is updating with NULL values

I am using Oracle and I am trying to update a table(A) with data from another table(B). Not every field in B has a value so I have a number of NULL entries. When I run the update it says 6000 rows updated. Now there are 6000 rows in table B, however for this query only 14 have data in. When I select count(*) from both tables for this value they both return 14 rows each. Why is it reporting that 6000 rows have been updated?
UPDATE
table1 A
SET
phone_work = (
SELECT B.phone_work
FROM table2 B
WHERE B.id = A.applicant_id)
WHERE EXISTS (
SELECT 1
FROM table2 B
WHERE B.id = A.applicant_id);
I have also tried the following and I get the same result:
UPDATE
table1 A
SET
phone_work = (
SELECT B.phone_work
FROM table2 B
WHERE B.id = A.applicant_id
AND B.phone_work is not null
)
WHERE EXISTS (
SELECT 1
FROM table2 B
WHERE B.id = A.applicant_id);
Why is it reporting the update of 6000 rows? When I change the fields but use the same syntax it reports updating of the exact number of rows I expect e.g. a count of table B has 86 entries in the NAME field and it reports 86 rows updated. It seems that with the phone_work field I am getting every null value being counted as an update.
Perhaps you want to check for the non-NULL value in the exists:
UPDATE table1 A
SET phone_work = (SELECT B.phone_work
FROM table2 B
WHERE B.id = A.applicant_id
)
WHERE EXISTS (SELECT 1
FROM table2 B
WHERE B.id = A.applicant_id AND B.phone_work IS NOT NULL
);
Try this:
UPDATE
(
SELECT A.phone_work Aphone, B.phone_work Bphone
FROM table2 B, table1 A
WHERE B.id = A.applicant_id AND B.phone_work IS NOT NULL
)
SET
Aphone = Bphone;
Source: Oracle SQL: Update a table with data from another table

SQL UPDATE from multiple rows to single row

this illustrates the issue:
CREATE TABLE Table_A (id int, value char)
INSERT INTO Table_A VALUES (1, 'A')
INSERT INTO Table_A VALUES (2, 'B')
CREATE TABLE Table_B (id int, value char)
INSERT INTO Table_B VALUES (1, 'C')
INSERT INTO Table_B VALUES (1, 'D')
If you run
UPDATE a SET a.value = (SELECT b.value FROM Table_B b WHERE a.id = b.id)
FROM Table_A a, Table_B b WHERE a.id = b.id
You get an error saying
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
But if you run this
UPDATE a SET a.value = b.value
FROM Table_A a, Table_B b WHERE a.id = b.id
No error is thrown and you get the row updated, why is that?
Edit:
Sorry guys, you seem to focusing on explaining why the first query gives error, but I think that is obvious and to me that is a desire result (because setting value of Table_A for id 1 to value of Table_B with id 1 is undefined when there are multiple values in Table_B with id 1)
My question is actually asking why the second query does not give you an error, which is causing trouble to me (i.e. I want it to break if I have more than one row with the same id but different values)
You got that error because you are using subquery when you set a new value and the subquery return more than 1 result.
SET a.value = (SELECT b.value FROM Table_B b WHERE a.id = b.id)
It will error when update a value with id = 1, because there is two record that have id = 1 in table b.
So your query will look like this (this is only for illustration and of course will cause an error)
UPDATE a SET a.value = ('C', 'D')
FROM Table_A a, Table_B b WHERE a.id = b.id
When you're using this query
UPDATE a SET a.value = b.value
FROM Table_A a, Table_B b WHERE a.id = b.id
You are join the table a with table b using id field, so the result is
a.id => a.value => b.value : 1 A C
a.id => a.value => b.value : 1 A D
No entry record for id = 2 because there is no matching record in table b.
So your update query will looks like this
UPDATE a SET a.value = 'C'
FROM Table_A a, Table_B b WHERE a.id = 1
UPDATE a SET a.value = 'D'
FROM Table_A a, Table_B b WHERE a.id = 1
Because your subquery will return both more than 1 result. The Assign statement will not accept more than 1 value.
You have to use JOIN
May be something like this
UPDATE A
SET A.value = B.value
FROM Table_A A INNER JOIN Table_B B ON A.id = B.id
FIDDLE DEMO
The reason your second query does not error our is because it will assign the first available B.value to a.value where it satisfies the condition
A.id = B.id
Try the following snippet and you will see how the Update...Set works.
create table #temp (id int, name varchar(100), phone int)
create table #temp1 (id int, phone int)
insert into #temp (id, name)
select 1, 'Mark' union
select 2, 'JOhn' union
select 3, 'Jerry'
insert into #temp1 (id, phone)
select 1, 123456 union
select 1, 222564 union
select 1, 222210
select * from #temp
select * from #temp1
update t
set phone = t1.phone
from #temp1 t1, #temp t
where t.id = t1.id
select * from #temp