Array_agg containing distinct structs - google-bigquery

I'm attempting to create an array with distinct struct as values for a column, something like so
select array_agg(distinct struct(field_a, field_b)) as c FROM tables ...
is that possible?

#standardSQL
SELECT ARRAY_AGG(STRUCT(field_a, field_b)) c
FROM (
SELECT DISTINCT field_a, field_b
FROM `project.dataset.table`
)

Related

How to union an array when grouping?

I am trying to combine multiple array columns into one with distinct elements and then get a count of distinct elements. How can I do something like that in postgres?
create temp table t as ( select 'james' as fn, array ['bond', 'milner'] as ln );
create temp table tt as ( select 'james' as fn, array ['mcface', 'milner'] as ln );
-- expected value: james, 3
select x.name,
array_length()-- what to do here?
from (
select fn, ln
from t
union
select fn, ln
from tt
) as x
group by x.name
You should unnest the arrays in the inner queries:
select x.fn,
count(elem)
from (
select fn, unnest(ln) as elem
from t
union
select fn, unnest(ln) as elem
from tt
) as x
group by x.fn
Db<>fiddle.
Why do you (want to) use arrays? That's not needed. Simply have a derived table using UNION, which eliminates duplicates, GROUP BY the name and use count().
SELECT name,
count(*)
FROM (SELECT name,
ln
FROM t
UNION
SELECT name,
ln
FROM tt) AS x
GROUP BY name;
db<>fiddle
Side note: 9.3 is out of support for a while. Consider upgrading.

Defining a subtable and then query from that table using SQL

I have a table with many columns, and I want to count the unique values of each column. I know that I can do
SELECT sho_01, COUNT(*) from sho GROUP BY sho_01
UNION ALL
SELECT sho_02, COUNT(*) from sho GROUP BY sho_02
UNION ALL
....
Here sho is the table and sho_01,.... are the individual columns. This is BigQuery by the way, so they use UNION ALL.
Next, I want to do the same thing, but for a subset of sho, say SELECT * FROM sho WHERE id in (1,2,3). Is there a way where I can create a subtable first, and then query the subtable? Something like this
SELECT * FROM (SELECT * FROM sho WHERE id IN (1,2,3)) AS t1;
SELECT sho_01, COUNT(*) from t1 GROUP BY sho_01
UNION ALL
SELECT sho_02, COUNT(*) from t1 GROUP BY sho_02
UNION ALL
....
Thanks
Presumably, the columns are all of the same type. If so, you can simplify this using arrays:
select el.which, el.val, count(*)
from (select t1.*,
array[struct('sho_01' as which, sho_01 as val),
struct('sho_2', show_02),
. . .
] as ar
from t
) t cross join
unnest(ar) el
group by el.which, el.val;
You can then easily filter however you want by adding a where clause before the group by.
Below is for BigQuery Standard SQL and allows you to avoid manual typing of column names or even knowing them in advance
#standardSQL
SELECT
TRIM(SPLIT(kv, ':')[OFFSET(0)], '"') column,
SPLIT(kv, ':')[OFFSET(1)] value,
COUNT(1) cnt
FROM `project.dataset.table` t,
UNNEST(SPLIT(TRIM(TO_JSON_STRING(t), '{}'))) kv
GROUP BY column, value
-- ORDER BY column, value

group by JSON Column that contains an array

I have the following table:
that contains these data:
How can I group by my array items in my JSON Column? and get this result:
You can try to use OPENJSON with CROSS APPLY to make it.
SELECT
col1,
UserID
FROM T t1
CROSS APPLY
OPENJSON(t1.Roles)
WITH
(
col1 varchar(50) N'$'
) AS a
sqlfiddle
If you cannot use OPENJSON, here is an alternative
Select
aRole, COUNT(*) as cnt
From (
Select
a.ID
,b.Items as aRole
From
(Select *
,replace(replace(replace(Roles,'[',''),']',''),'"','') as Rolesx
From JSONgroup) a
Cross Apply dbo.Split(a.Rolesx, ',') b
) c
group by aRole

Distinct values from two columns

This is the query which I am using to get the distinct values:
SELECT DISTINCT
LOGIN_BY,
RECEIVED_BY
FROM SAMPLE
My requirement is I need the distinct values of both the columns as a single output. Is there any way to do that?
try this
(SELECT DISTINCT LOGIN_BY as ID from sample )
union all
(Select Distinct RECEIVED_BY as ID FROM SAMPLE)
Try it like this:
select distinct a from (
select
distinct LOGIN_BY as a
from
SAMPLE
union
select
distinct RECEIVED_BY as a
from
SAMPLE
);
This works for me on an Oracle database.

Select values that exist in all arrays in Postgres

I've got some table ignore with col ignored_entry_ids contains array of integer. For example:
id ignored_entry_ids
1 {1,4,6}
2 {6,8,11}
3 {5,6,7}
How can I select numbers that exists in every row with array? (6 in examle)
If your numbers are unique inside array, you can do something like this, don't think it could be made without unnest
with cte as (
select id, unnest(ignored_entry_ids) as arr
from ign
)
select arr
from cte
group by arr
having count(*) = (select count(*) from ign)
sql fiddle demo
if numbers are not unique, add distinct:
with cte as (
select distinct id, unnest(ignored_entry_ids) as arr
from ign
)
select arr
from cte
group by arr
having count(*) = (select count(*) from ign)