I have two sqlite tables, both with the same column layout. I would like to merge the two tables (or update table 1), taking values from table 2 if they are not null, otherwise, taking them from table 1. Is there a better way of doing this this short of an UPDATE with multiple case clauses (similar to the approach in SQLITE UPDATE field IF NULL from another table)? The tables have a large number of columns which would make such a statement quite long.
table 1
|-------+-------+--------+----+--------|
| id | col1 | col2 | .. | col100 |
|-------+-------+--------+----+--------|
| 2346a | apple | red | | WA |
| d27d7 | pear | green | | VA |
| 568ba | lemon | yellow | | CA |
| 9896f | grape | purple | | CA |
| 1b7da | peach | pink | | CA |
|-------+-------+--------+----+--------|
table 2
|-------+-------+--------+----+--------|
| id | col1 | col2 | .. | col100 |
|-------+-------+--------+----+--------|
| 2346a | null | green | | null |
| 1b7da | null | null | | GA |
| 9896f | plum | null | | null |
|-------+-------+--------+----+--------|
desired result
|-------+-------+--------+----+--------|
| id | col1 | col2 | .. | col100 |
|-------+-------+--------+----+--------|
| 2346a | apple | green | | WA |
| d27d7 | pear | green | | VA |
| 568ba | lemon | yellow | | CA |
| 9896f | plum | purple | | CA |
| 1b7da | peach | pink | | GA |
|-------+-------+--------+----+--------|
You can bring table2 with a left join and prioritize non-null values from table2 using coalesce():
select
t1.id,
coalesce(t2.col1, t1.col1) col1,
coalesce(t2.col2, t1.col2) col2,
...
coalesce(t2.col100, t1.col100) col100
from table1 t1
left join table2 t2 on t2.id = t1.id
You can use ROW VALUES to update Table1:
update Table1
set (col1, col2, col100) = (
select
coalesce(t2.col1, Table1.col1),
coalesce(t2.col2, Table1.col2),
................................
coalesce(t2.col100, Table1.col100)
from Table2 t2
where t2.id = Table1.id
)
where exists (select 1 from Table2 t2 where t2.id = Table1.id);
See the demo.
Results:
| id | col1 | col2 | col100 |
| ----- | ----- | ------ | ------ |
| 2346a | apple | green | WA |
| d27d7 | pear | green | VA |
| 568ba | lemon | yellow | CA |
| 9896f | plum | purple | CA |
| 1b7da | peach | pink | GA |
My goal is to add another column to an existing table, to see if the value/conditions exists in a group and appropriately labeling the entire group if it is present or not.
If a Team has one project with a budget >= 20M or Actual_Spend >=2.5M I want to label the Team and all it's projects as Table 1 in the Category column. Irrespective if the other projects within the same Team fit this criteria.
I will provide a SQL fiddle link w/ my solution: http://sqlfiddle.com/#!18/3ddaf/12/0
I'm ending up with two extra columns of "Team" and "Category" and not sure how they're ending up there.
Below is the end result I'm looking for. I'm open to better solutions than the one I provided.
Thank you for your time
| Team | ProjectID | Budget | Actual_Spend | State | Category |
|------|-----------|----------|--------------|------------|----------|
| Cyan | 2 | NULL | NULL | Utah | Table 1 |
| Blue | 1 | NULL | 3000000 | California | Table 1 |
| Cyan | 1 | 20000000 | 1000000 | Utah | Table 1 |
| Blue | 2 | 22000000 | NULL | California | Table 1 |
| Red | 1 | 7000000 | 1000000 | Washington | Table 2 |
| Red | 2 | 19999000 | 2490000 | Oregon | Table 2 |
| Gray | 1 | 19000000 | 2500000 | Utah | Table 1 |
| Gray | 1 | 10000000 | 500000 | Utah | Table 1 |
Providing code to create the dataset:
Create Table Source_Data
(
Team varchar(50),
ProjectID INT,
BUDGET INT,
Actual_Spend INT,
State varchar(max),
)
INSERT INTO Source_Data
VALUES
('Blue',1,NULL,3000000,'California'),
('Green',1,20000000,1000000,'Utah'),
('Blue',2,22000000,NULL,'California'),
('Green',2,NULL,NULL,'Utah'),
('Red',1,7000000,1000000,'Washington'),
('Red',2,19999000,2490000,'Oregon'),
('Yellow',1,19000000,2500000,'Utah'),
('Yellow',1,10000000,500000,'Utah');
I think that you are looking for window functions:
select
s.*,
min(case when Budget>=20000000 or Actual_Spend>=2500000 then 'Table1' else 'Table2' end)
over(partition by team) Category
from Source_Data s
If any of the records having the same team satisfies condition Budget>=20000000 or Actual_Spend>=2500000, the new column yields Table1, else it produces Table2.
Demo on DB Fiddle:
Team | ProjectID | Budget | Actual_Spend | State | Category
:--- | --------: | -------: | -----------: | :--------- | :-------
Blue | 2 | 22000000 | null | California | Table1
Blue | 1 | null | 3000000 | California | Table1
Cyan | 1 | 20000000 | 1000000 | Utah | Table1
Cyan | 2 | null | null | Utah | Table1
Gray | 1 | 19000000 | 2500000 | Utah | Table1
Gray | 1 | 10000000 | 500000 | Utah | Table1
Red | 1 | 7000000 | 1000000 | Washington | Table2
Red | 2 | 19999000 | 2490000 | Oregon | Table2
I have a Text String which contains JSON, something like this:
'{ "d" : [ "test0", "test1", "test2" ] }'
and I would like to retrieve the item of the Array as rows.
+------------+
| data |
+------------+
| test0 |
| test1 |
| test2 |
+------------+
all examples on the Web, show how it is done with "Object Array", but I would like to do it with a simple "String Array" MS example.
The default query
select * from OPENJSON('{"d":["test0","test1","test2"]}', '$.d')
just returns a table with the key, value, type of each entry
+-----+-------+------+
| key | value | type |
+-----+-------+------+
| 0 | test0 | 1 |
| 1 | test1 | 1 |
| 2 | test2 | 1 |
+-----+-------+------+
the problem is, I don't know how to set the with part of the query, so that the query returns a row.
select * from OPENJSON('{"d":["test0","test1","test2"]}', '$.d')
with(data nvarchar(255) '$.d')
only return:
+------+
| data |
+------+
| NULL |
| NULL |
| NULL |
+------+
select * from OPENJSON('{"d":["test0","test1","test2"]}', '$.d')
with(data nvarchar(255) '$')
I have two tables (each with about 20 columns), none of the column names match up but some of the values in 1 column match the values in another (see below).
I want to get a the combination of the 2 tables on certain columns based on True/False values in a column on the primary table.
I am doing all of this using the SQLServer Third Party JDBC Drivers in Oracle's SQL Developer (I am not sure if or how that might have an effect on my syntax).
I am sure that this is simple, but I cannot find any examples that do this and I am just too new to SQL to wrap my head around it.
CREATE TABLE [dbo].[TableA] (
[colA1] VARCHAR (10) NULL,
[colA2] VARCHAR (10) NULL,
[colA3] VARCHAR (10) NULL,
[colA4] VARCHAR (10) NULL,
[colA5] VARCHAR (10) NULL,
[colA6] INT NULL,
[colKey] INT NOT NULL,
CONSTRAINT [PK_TableA] PRIMARY KEY CLUSTERED ([colKey] ASC)
);
CREATE TABLE [dbo].[TableB] (
[colB1] VARCHAR (10) NULL,
[colB2] VARCHAR (10) NULL,
[colB3] VARCHAR (10) NULL,
[colB4] INT NULL,
[colKey] INT NOT NULL,
PRIMARY KEY CLUSTERED ([colKey] ASC)
);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (1,'AC1-1','AC2-1','AC3-1',NULL,'FALSE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (2,'AC1-2','AC2-2','AC3-2',NULL,'FALSE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (3,'AC1-3',NULL,NULL,'AC4-3','TRUE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (4,'AC1-4',NULL,NULL,'AC4-4','TRUE',2016);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (5,'AC1-5','AC2-5','AC3-5',NULL,'FALSE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (6,'AC1-6','AC2-6','AC3-6',NULL,'FALSE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (7,'AC1-7',NULL,NULL,'AC4-7','TRUE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (8,'AC1-8',NULL,NULL,'AC4-8','TRUE',2015);
INSERT INTO TableA(colKey,colA1,colA2,colA3,colA4,colA5,colA6) VALUES (9,'AC1-9',NULL,NULL,'AC4-9','TRUE',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (1,'AC4-3','BC2-1','BC3-1',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (2,'AC4-4','BC2-2','BC3-2',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (3,'AC4-4','BC2-3','BC3-3',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (4,'AC4-3','BC2-4','BC3-4',2016);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (5,'AC4-7','BC2-5','BC3-5',2015);
INSERT INTO TableB(colKey,colB1,colB2,colB3,colB4) VALUES (6,'AC4-8','BC2-6','BC3-6',2015);
TableA
+-------+--------+--------+--------+-------+-------+
| colA1 | colA2 | colA3 | colA4 | colA5 | colA6 |
+-------+--------+--------+--------+-------+-------+
| AC1-1 | AC2-1 | AC3-1 | (Null) | FALSE | 2016 |
| AC1-2 | AC2-2 | AC3-2 | (Null) | FALSE | 2016 |
| AC1-3 | (Null) | (Null) | AC4-3 | TRUE | 2016 |
| AC1-4 | (Null) | (Null) | AC4-4 | TRUE | 2016 |
| AC1-5 | AC2-5 | AC3-5 | (Null) | FALSE | 2015 |
| AC1-6 | AC2-6 | AC3-6 | (Null) | FALSE | 2015 |
| AC1-7 | (Null) | (Null) | AC4-7 | TRUE | 2015 |
| AC1-8 | (Null) | (Null) | AC4-8 | TRUE | 2015 |
| AC1-9 | (Null) | (Null) | AC4-9 | TRUE | 2016 |
+-------+--------+--------+--------+-------+-------+
TableB
+-------+-------+-------+-------+
| colB1 | colB2 | colB3 | colB4 |
+-------+-------+-------+-------+
| AC4-3 | BC2-1 | BC3-1 | 2015 |
| AC4-4 | BC2-2 | BC3-2 | 2015 |
| AC4-4 | BC2-3 | BC3-3 | 2016 |
| AC4-3 | BC2-4 | BC3-4 | 2016 |
+-------+-------+-------+-------+
Results Table
+-------+--------+-------+-------------------------+-------------------------+
| colA1 | colA4 | colA5 | combined(colA2 & colB2) | combined(colA3 & colB3) |
+-------+--------+-------+-------------------------+-------------------------+
| AC1-1 | (null) | FALSE | AC2-1 | AC3-1 |
| AC1-2 | (null) | FALSE | AC2-2 | AC3-2 |
| AC1-3 | AC4-3 | TRUE | BC2-1 | BC3-1 |
| AC1-4 | AC4-4 | TRUE | BC2-2 | BC3-2 |
| AC1-9 | AC4-9 | TRUE | (null) | (null) |
+-------+--------+-------+-------------------------+-------------------------+
So I think I need some kind of SELECT like this:
SELECT colA1, colA5,
IF colA5 = True
THEN colB2, colB3, etc.
ELSE colA2, ColA3, etc.
FROM tableB, tableA
WHERE colA1 = colB1 AND colB4 = 2016 AND colA6 = 2016
I have tried this:
SELECT A.colA1
,A.colA4
,A.colA5
,CASE
WHEN A.colA5 = TRUE
THEN B.colB2
ELSE A.colA2
END AS 'combined(colA2 & colB2)'
,CASE
WHEN A.colA5 = TRUE
THEN B.colB3
ELSE A.colA4
END AS 'combined(colA3 & colB3)'
,
FROM TableA A
,TableB B
WHERE A.colA6 = '2016'
AND B.colB4 = '2016'
AND (
A.colA4 = B.colB1
OR A.colA4 IS NULL
)
what I get is this:
+-------+-------+-------+-------------------------+-------------------------+
| colA1 | colA4 | colA5 | combined(colA2 & colB2) | combined(colA3 & colB3) |
+-------+-------+-------+-------------------------+-------------------------+
| AC1-3 | AC4-3 | TRUE | BC2-1 | BC3-1 |
| AC1-4 | AC4-4 | TRUE | BC2-2 | BC3-2 |
+-------+-------+-------+-------------------------+-------------------------+
So I am missing the rows were TableA/colA5 are FALSE. Also, I need 12 of these "combined" columns, is there a way that I can avoid using 12 CASE statements?
After learning about joins and case here is the answer (though apparently I will have to use the 12 CASE statements that I would have preferred to avoid).
SELECT A.colA1
,A.colA4
,A.colA5
,CASE
WHEN A.colA5 = 'TRUE'
THEN B.colB2
ELSE A.colA2
END AS 'combined(colA2 & colB2)'
,CASE
WHEN A.colA5 = 'TRUE'
THEN B.colB3
ELSE A.colA3
END AS 'combined(colA3 & colB3)'
FROM TableA A LEFT JOIN TableB B ON A.colA4 = B.colB1
WHERE (A.colA6 = '2016' and A.colA5 ='FALSE')
or (A.colA6 = '2016' and A.colA5 ='true' and B.colB4 = '2016')
or (A.colA6 = '2016' and A.colA5 ='true' and B.colB4 is null)
;