BigQuery count each item in array across table - sql

I cannot quite find what I'm looking for, so here goes:
I'm looking for a way to get a count of the number of times an item occurs in an array across the entire table.
Imagine you have a table child_names with two columns - user_id and children
I know it's unusual to have two children with same name, but bear with me
.
user_id children
1 Bob, Jane, Bob
2 Jeff, Jane
3 Bob, Matt
4 Jane, John
I am looking for a result that would have two columns
Bob 3
Jane 3
Jeff 1
Matt 1
John 1
So far I have this
SELECT
ARRAY(
SELECT AS STRUCT child, `count`
FROM t.children child
LEFT JOIN (
SELECT AS STRUCT child, COUNT(1) `count`
FROM t.children child
GROUP BY child
) stats
USING(child)
) hashtag
FROM `child_names` t,
UNNEST(children)
But this gives me a count of how many children have that name per parent, not per table.
I get
Bob 2
Jane 1
Jeff 1
Jane 1
Bob 1
Matt 1
etc.
I hope that makes sense. Any help would be appreciated.

Use below
SELECT name, COUNT(*) cnt
FROM child_names,
UNNEST(children) name
GROUP BY name
if applied to sample data in your question - output is

Related

count different column values after grouping by

Consider this table:
id name department email
1 Alex IT blah#gmail.com
1 Alex IT blah#gmail.com
2 Jay HR jay#gmail.com
2 Jay Marketing zou#gmail.com
If I group byid,name and count I get:
id name count(*)
1 Alex 2
2 Jay 2
With this query:
select id,name,count(*) from tb group by id,name;
However I would like to count only records that diverge from department,email, so as to have:
id name count(*)
1 Alex 0
2 Jay 1
This time the count for the first group 1,Alex is 0 because department,email have the same values (duplicated) , on the other hand 2,Jay is one because department,email has one different value.
If you meant "two different values" for "Jay", you can use distinct:
select id,name,count(*) from (SELECT distinct * FROM tb) group by id,name;
You can use count(*) - 1 to get similar results in your question.

SQL field default "count(another_field) +1"

I need to create a field COUNT whose default value is the automatically generated count of times NAME has appeared in that table till now, as shown in example below. Since i am adding the field to an existing table, i also need to populate existing rows. How best to go about this please?
ID NAME COUNT
1 peter 1
2 jane 1
3 peter 2
4 peter 3
5 frank 1
6 jane 2
7 peter 4
You would do this when you are querying the table, using the ANSI-standard row-number function:
select id, name, row_number() over (partition by name order by id) as seqnum
from t;

SQL: How do you count the number of unique records?

I'm new to SQL and sorry if this q has been asked before - I couldn't phrase it properly.
Say I have a table that looks like this:
Name Call ID
Sally 1
Sally 2
Sally 3
Mike 4
Mike 5
Bob 6
Bob 7
I want to create a new table that looks like this:
Name No. of calls
Sally 3
Mike 2
Bob 2
Attempt
I assume I would do something like:
SELECT
Name,
COUNT(distinct Name) AS No. of Calls
FROM Table
Thanks.
You just need to group them and that's all.
SELECT
Name
COUNT(*) AS [No. of Calls]
FROM
Table
GROUP BY
Name
You're looking for GROUP BY:
SELECT Name, COUNT(*) AS 'No. of Calls'
FROM Table
GROUP BY NAME
ORDER BY COUNT(*) DESC

How do I save multiple values and extra and use them in Sqlite?

I have 2 tables e.g.
First table
ID Value
1 Apple
2 Orange
3 Banana## ...
Second Table
PERSON FRUIT
Amy 1
Peter 2
Charlie 1,2
Dick 2,3
I would like to for example save what fruits the users have in just one column. So that when I call out what Charlie wants, I can somehow receive and output of Apple, Orange; and for Dick - Orange, Banana etc.
I am not really sure where to start on achieving this. Is it possible to do it purely in an SQL select statement alone?
You could implement a link table. For example.. you have a Fruit Table, which stores all the unique fruits, and you have a Person table that stores all unique people.
So you should create a third table that links unique fruits to people for example...
ID FRUIT PERSON
1 1 1
2 1 2
3 2 1
etc... then a select on the link table with the person ID, would bring up all the fruits that person likes.

Oracle find common value in two different columns

If I have a structure like this:
CREATE TABLE things (
id,
personA varchar2,
personB varchar2,
attribute ...,
)
And I want to find, for a given attribute, if I have at least 1 common person for all my things, how would I go about it?
So if my data is (and it could be more than 2 per attribute):
1, John, Steve, Apple
2, Steve, Larry, Apple
3, Paul, Larry, Orange
4, Paul, Larry, Orange
5, Chris, Michael, Tomato
6, Steve, Larry, Tomato
For Apple, Steve is my common person, For Orange both Paul and Larry are, and for Tomato I have no common people. I don't need a query that returns all of these at once, however. I have one of these attributes and want 0, 1, or 2 rows depending on what kind of commonality I have. I've been trying to come up with something but can't quite figure out.
This will give you your common person / attribute list. I ran it against your sample data and got the expected result. Hope it's at least pointing in the right direction :)
WITH NormNames AS (
SELECT PersonA AS Person, Attribute FROM things
UNION ALL SELECT PersonB AS Person, Attribute FROM things
)
SELECT
Person, Attribute, COUNT(*)
FROM NormNames
GROUP BY Person, Attribute
HAVING COUNT(*) >= 2
If you're on 11gR2 you could also use the unpivot operator to avoid the self-join:
select person, attribute
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
group by person, attribute
having count(*) > 1;
PERSON ATTRIBUTE
---------- ----------
Steve Apple
Paul Orange
Larry Orange
3 rows selected.
Or to just the the people who match the attribute, which I think is what the end of your question is looking for:
select person
from (
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'))
)
where attribute = 'Apple'
group by person, attribute
having count(*) > 1;
PERSON
----------
Steve
1 row selected.
The unpivot translates columns into rows. Run on its own it transforms your original six rows into twelve, replacing the original persona/personb columns with a single person and an additional column indicating which column the new row was formed from, which we don't really care about here:
select *
from things
unpivot (person for which_person in (persona as 'A', personb as 'B'));
ID ATTRIBUTE W PERSON
---------- ---------- - ----------
1 Apple A John
1 Apple B Steve
2 Apple A Steve
2 Apple B Larry
3 Orange A Paul
3 Orange B Larry
4 Orange A Paul
4 Orange B Larry
5 Tomato A Chris
5 Tomato B Michael
6 Tomato A Steve
6 Tomato B Larry
12 rows selected.
The outer query is then doing a simple group.
Here's one method.
It implements an unpivot method by cross-joining to a list of numbers (you could use the unpivot method Alex uses) and then joins the result set, hopefully with a hash join for added goodness.
with
row_generator as (
select 1 counter from dual union all
select 2 counter from dual),
data_generator as (
select
attribute,
id ,
case counter
when 1 then persona
when 2 then personb
end person
from
things,
row_generator)
select
t1.attribute,
t1.person
from
row_generator t1,
row_generator t2
where
t1.attribute = t2.attribute and
t1.person = t2.person and
t1.id != t2.id;