Select everything except one column in ARRAY_AGG + STRUCT in BigQuery - arrays

I'm currently using ARRAY_AGG + STRUCT to nest all the fields in my table under one column and yes, it works. The problem is that the solution I'm using is not scalable. I'd like to select all the fields except for one in my STRUCT but I've no idea on how to do this. Here the sample:
SELECT
Col1,
ARRAY_AGG(STRUCT(Col2,
Col3,
Col4,
Col5,
Col6,
Col7)) OVER (PARTITION BY Col3, Col4, Col5)
FROM
Source
And here what I'd like to have:
SELECT
Col1,
ARRAY_AGG(STRUCT(* EXCEPT(Col1))) OVER (PARTITION BY Col3, Col4, Col5)
FROM
Source

Below is for BigQuery Standard SQL
#standardsql
select col1,
array_agg((select as struct * except(col1) from unnest([t])))
over(partition by col3, col4, col5)
from source t

Related

Google sheets query search box to search a value in different columns

good night/day.
I've been having issues to search a value no matter the column, for example If I need a specific value from col1, col3 or col4, I would only need to type the value I need in Cell B1 no matter if it is lowercase or uppercase , But can't find the way to solve it.
=QUERY(IMPORTRANGE(Links!C2,"Supply!A2:L"),
"SELECT Col1, Col2, Col3, Col4, Col6, Col7, Col11, Col10, Col9, Col8, Col12
WHERE lower('Col1&Col3&Col4') CONTAINS '"&LOWER(B1)&"'",0)
Instead It drops me #N/A (Error
Query completed with an empty output) when searching for a specific value in Cell B1.
Thanks and have a good one, whoever can help me out!
try:
=ARRAYFORMULA(QUERY({IMPORTRANGE(Links!C2,"Supply!A2:L"),
IMPORTRANGE(Links!C2,"Supply!A2:A")&
IMPORTRANGE(Links!C2,"Supply!C2:C")&
IMPORTRANGE(Links!C2,"Supply!D2:D")},
"select Col1,Col2,Col3,Col4,Col6,Col7,Col11,Col10,Col9,Col8,Col12
where lower(Col13) contains '"&LOWER(B1)&"'", 0))

Federated queries in SnowFlake?

I have three organizations which want to collaborate. All three of them have the same backend database and tables, and want to run a federated query across these three tables. Is that possible using snowflake?
If they each have one "table" each, and data share it to the other two, that can have the three "tables" and
SELECT a.*, b.*, c.*
FROM mytable AS a
JOIN their_table_one AS b
JOIN the_other_table AS c
just fine.
You can import all tables into Snowflake and then create views that combine these tables so that they are visible as one view.
Example:
CREATE VIEW Table1_v
AS
SELECT col1, col2, col3, 'Source A' AS src
FROM SourceA_Table1
UNION ALL
SELECT col1, col2, col3, 'Source B' AS src
FROM SourceB_Table1
UNION ALL
SELECT col1, col2, col3, 'Source C' AS src
FROM SourceC_Table1;

Is it possible to create SQL query templates?

I have a couple of tables as data sources which have extremely similar structure. I only care about some columns of them and I want to join them. So what I do at the moment is:
SELECT 'table_a' AS source, col1, col2, col3, col4
FROM table_a as source_table
INNER JOIN other on source_table.id = other.id
UNION ALL
SELECT 'table_b' AS source, col1, col2, col3, col4
FROM table_b as source_table
INNER JOIN other on source_table.id = other.id
UNION ALL
SELECT 'table_c' AS source, col1, col2, col3, col4
FROM table_c as source_table
INNER JOIN other on source_table.id = other.id
UNION ALL
SELECT 'table_d' AS source, col1, col2, col3, col4
FROM table_d as source_table
INNER JOIN other on source_table.id = other.id
I would like to do something like this:
query(param1, param2) := {
SELECT param1 AS source, col1, col2, col3, col4
FROM param2 as source_table
INNER JOIN other on source_table.id = other.id
}
query('table_a', table_a)
UNION ALL
query('table_b', table_b)
UNION ALL
query('table_c', table_c)
UNION ALL
query('table_d', table_d)
I know how to do this within the programming language (using a templating engine and constructing the query string).
Is something like this possible within SQL (Snowflake Warehouse)?
You can't do exactly that I'm afraid. However, you can use Snowflake Stored Procedures (SP) to effectively achieve this. You can construct the SQL query text in SP based on the parameters passed to it, and then executing it. You can e.g. pass to it an array of table names etc.
One problem is that today SPs in Snowflake do not return the result of the query directly. To overcome this, you can e.g. save the result of the query in a new table (with the name hardcoded in SP, or passed as a parameter to SP) and then query it with a separate SELECT.

MSSQL error #120

I have the following sql:
INSERT INTO [dbo].[table1]
([col1],[col2],[col3],...[col14])
SELECT * FROM [dbo].Table2
GO
Running it throws MSSQL Err #120 which means the number of columns line up to the INSERT. table2 has 5 columns and table1 has 14. Would I be correct in assuming that this is the cause of the error? The reason I ask is that a) Not familiar with MSSQL and b) I am unfamiliar with their database.
Yes, this is the cause of your error.
You will have to:
INSERT INTO [dbo].[table1]
([col1],[col2],[col3],...[col14])
SELECT
col1, col2, col3, col4, col5, --your table's columns
'const1', null, 1, etc... --other values that you want for the other columns,
FROM [dbo].Table2 --defaults, constants, null, etc.
GO
or
INSERT INTO [dbo].[table1]
([col1],[col2],[col3],[col4],[col5]) --the rest will have their default value.
SELECT
col1, col2, col3, col4, col5
FROM [dbo].Table2
GO

What's the most efficient syntax to use Merge to upsert many rows at once?

There's 2 ways I've found of upserting many rows into a table with SQL Server 2008.
One of which is found here http://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx says to create a temp table, then insert values to temp table, and finally merge that table with target able.
This doesn't seem very efficient to me because you have to create a table, fill the table, merge to target table, and then delete the temp table.
The only other thing I can think of is as follows...
MERGE dbo.targettable as tgt
USING (
SELECT 12 as col1, 13 as col2, 'abc' as col3, 'zyx' as col4
UNION ALL
SELECT 11 as col1, 11 as col2, 'def' as col3, 'def' as col4
(etc etc)
UNION ALL
SELECT 7 as col1, 10 as col2, 'jfj' as col3, 'tub' as col4)
as new
ON tgt.col1=new.col1
WHEN MATCHED THEN UPDATE SET tgt.col2=new.col2, tgt.col3=new.col3, tgt.col4=new.col4
WHEN NOT MATCHED THEN INSERT (col1, col2, col3, col4)
VALUES(new.col1, new.col2, new.col3, new.col4);
Based on usr's answer I was able to find http://msdn.microsoft.com/en-us/library/bb510625.aspx
I think this is the way to do it. Could someone verify that this syntax appears correct?
MERGE dbo.targettable as tgt
USING (VALUES(12, 13, 'abc', 'zyx'), (11, 11, 'def', 'def'),(7, 10, 'jfj', 'tub'))
AS new (col1, col2, col3, col4)
ON tgt.col1=new.col1
WHEN MATCHED THEN UPDATE SET tgt.col2=new.col2, tgt.col3=new.col3, tgt.col4=new.col4
WHEN NOT MATCHED THEN INSERT (col1, col2, col3, col4)
VALUES(new.col1, new.col2, new.col3, new.col4);
Where does the data to be merged come from?
If it comes from a query, inline the query into the merge.
If it
comes from the app, use table-valued parameters.
If it is generated
iteratively, use a temp table or table variable.
If it is a constant like in your example use the VALUES clause. Don't use UNION ALL because it is more verbose, does not document semantics nicely and increases query compile time because the optimizer has to convert it to VALUES form.

Resources