BigQuery: Select column if it exists, else put NULL? - sql

I am updating a daily dashboard. Assume everyday I have two tables TODAY and BEFORE_TODAY. What I have been doing daily was something like:
SELECT a, b FROM TODAY
UNION ALL
SELECT a,b FROM BEFORE_TODAY;
TODAY table is generated daily and is appended to all the data before it. Now, I need to generate a new column say c and in order to UNION ALL the two, I need that to be available on BEFORE_TODAY as well.
How can I add a conditional statement to BEFORE_TODAY to check if I have a c column and use that column, else use NULL instead of it.

Something is wrong with your data model. You should be putting the data into separate partitions of the same table. Then you would have no problems. You could just query the master table for the partitions you want. The column would appear in the history, with a NULL value.
That is the right solution. You can create a hacked solution, assuming that your tables have a primary key. For instance, if a, b is unique on each row, you could do:
select t.a, t.b, t.c
from today t
union all
select b.a, b.b,
(select c -- not qualified on purpose
from before_today b2
where b2.a = b.a and b2.b = b.b
) as
from before_today b cross join
(select null as c) c;
If b.c does not exist, then the subquery returns c.c. If it does exist this it returns b2.c from the subquery.

Although by combining dynamic SQL and INFORMATION_SCHEMA, you can write a script to achieve what you told, this doesn't seems to be the right thing to do.
As part of your data model planning, you should add column c to BEFORE_TODAY ahead of time. The newly added column on existing rows will always have NULL value. Then you can add column to TODAY and reference column c as normal.

Related

How to choose all column of a single table in a joined table?

I have a query that is like this:
SELECT * FROM A JOIN B
Table A and B are almost equal, but I use the join to filter on certain rows. Now my result table is having all columns twice, and this is causing referencing trouble where I am using this table. Therefore I would like to only show table A's columns. Is there a more easy way to achieve this than retyping all column names on the spot of *?
If you only want the columns from A, then use:
select A.*
You can add additional columns as you like:
select A.*, B.special_column

SQL SELECT query where the IDs were already found

I have 2 tables:
Table A has 3 columns (for example) with opportunity sales header data:
OPP_ID, CLOSE_DTTM, STAGE
Table B has 3 columns with the individual line items for the Opportunities:
OPP_LINE_ID, OPP_ID, AMOUNT_USD
I have a select statement that correctly parses through Table A and returns a list of Opportunities. What I would like to do is, without joining the data, to have a SELECT statement that will get data from Table B but only for the OPP_IDs that were found in my first query.
The result should be 2 views/resultset (one for each select query) and not just 1 combined view where Table B is joined to Table A.
The reason why I want to keep them separate is because I will have to perform a few manipulations to the result from table B and i don't want the result from table A affected.
Subquery is all what you need
SELECT OPP_ID, CLOSE_DTTM, STAGE
From table a
where a.opp_id IN (Select opp_id from table b)
Presuming you're using this in some client side data access library that represents B's data in some 2 dimensional collection and you want to manipulate it without affecting/ having A's data present in that collection:
Identify the records in A:
SELECT * FROM a WHERE somecolumn = 'somevalue'
Identify the records in B that relate to A, but don't return A's data:
SELECT b.* FROM a JOIN b ON a.opp_id = b.opp_id WHERE a.somecolumn = 'somevalue'
Just because JOIN is used doesn't mean your end-consuming program has to know about A's data. You could also use IN, like the other answer does, but internally the database will rewrite them to be the same thing anyway
I tend to use exists for this type of query:
select b.*
from b
where exists (select 1 from a where a.opp_id = b.opp_id);
If you want two results sets, you need to run two queries. It is unclear what the second query is, perhaps the first query on A.

How to populate query with result from different table?

I have two tables. Table A and table B. Table A has a column that is a reference to the primary key to table B. I want to run a select query on table A and then populate the column that referrers to B with all of the data in that row of B.
SELECT * from A a LEFT JOIN B b ON a."b_id" = b."id" WHERE ...
That gives a result with each row containing all of the columns of A and all of the columns of B. It is a confusing mess to figure out which column is from which table. I want to be able to do something like.
row.A."column name"
row.B."column name"
I don't want to have to rename every single column using AS. There must be a better way to do this.
Not a 100% sure what your asking but what I think your asking is.
You want a way to have only column B values to show? If so you could do:
SELECT B.*
FROM A
JOIN B
ON A.b_id = B.id
That will only get you the B columns and data, If you want A also maybe do but you want to have it separate from b maybe do:
SELECT B.*,'|' AS ['|'], A.*
FROM A
JOIN B
ON A.b_id = B.id
Hopefully this is helpful, if not to you maybe another reader.

SAS SQL JOIN increase rows instead of match rows

I have a problem with full outer join in SAS
I want to join two database.
A is the "mama" containing patient ID,SEX,RACE,blablabla...but dont have the status variable.
B is the one only containing ID and status.
So A is actually a way bigger database than B and what I'm going to do is to put B including status into A. Here's my code:
proc sql;
CREATE TABLE C AS
select *
from A full outer join B
on A.id=B.id ;
RUN;
The result I got is actually not merging two database. Instead, I got the database C, which all the data from A on the top(status variable is null), and then the data B following by A (status variable is there but all other variables are showing Null). Thus, what i did is just adding rows....
Here is some conditions on my codes;
1. I use the University Edition
2. the format of ID is actually Char. Since B's ID (example:BD123), I convert numeric variable ID from A into char variable .
Anybody could help me with this? Thank you very much :-D
If you got an entire concatenation (100 rows in A, 15 rows in B, 115 in C) then you likely didn't correctly match the ID variable format when you converted. You may have an issue with additional spaces or something to that effect (the length of B.id may not match A.id). If possible I would convert the ID to numeric, or do a more careful conversion to character.
Second, if you're intending to just get the number of rows of A back (just adding B information to A), then you want a left join not a full outer join.
I Think you might be looking at left join instead.
proc sql;
create table C as
select A.*, B.*
from A left join B
on A.ID=B.ID;
quit;

Complex SQL queries (DELETE)?

I'm working with three tables, and for simplicity's sake let's call them table A, B, and C. Both tables A and B have a column called id, as well as one other column, Aattribute and Battribute, respectively. Column c also has an id column, and two other columns which hold values for A.id and B.id. Now, in my code, I have easy access to values for both Aattribute and Battribute, and want to delete the row at C, so effectively I want to do something like this:
DELETE FROM C WHERE aid=(SELECT id FROM A WHERE Aattribute='myvalue') AND bid=(SELECT id FROM B WHERE Battribute='myothervalue')
But this obviously doesn't work. Is there any way to make a single complex query, or do I have to run three queries, where I first get the value of A.id using a SELECT with 'myvalue', then the same for B.id, then use those in the final query?
[Edit: it's not letting me comment, so in response to the first comment on this: I tried the above query and it did not work, I figured it just wasn't syntactically correct. Using MS Access, for what it's worth. ]
You must use IN instead of =.
DELETE
FROM C
WHERE aid IN
(SELECT id
FROM A
WHERE Aattribute='myvalue'
)
AND bid IN
(SELECT id
FROM B
WHERE Battribute='myothervalue'
)