How to merge a repeating value in Bigquery using SQL Function - sql

Is there a function in SQL for Bigquery where I can merge a repeating value?
This is the data
Date
Product
total_session_by_day
July 1
Product A
200
July 1
Product B
200
July 2
Product A
500
July 2
Product B
500
And this is the desired output in Bigquery.
Excel Output
The idea is when I select "July 1 and 2" and "Product A and/or B" on datastudio, the value of total_session_by_day is 700.
Hope someone could help. Thank you.

Replace SourceTable with your table's id:
SELECT
total_session_by_day,
ARRAY_AGG(
STRUCT(
`Date`,
Product
) AS r
)
FROM SourceTable
GROUP BY total_session_by_day
The output will look like this:

Related

Creating a JSON list from multiple table rows

I have data in a BigQuery table where every row is an item in an ecommerce order, for example here are rows showing the purchase of three items across two orders:
Order number
Product
Quantity
001
ABC
1
001
DEF
2
002
GHI
1
I need to create a JSON list for every order in the below format, which using the example data above would look like this for order 001:
[ {product_id: "ABC", quantity:1},{product_id: "DEF", quantity:2} ]
How can I achieve this format in BigQuery SQL?
Consider below
SELECT order_number,
TO_JSON_STRING(ARRAY_AGG(STRUCT(product as product_id, quantity))) json_value
FROM orders
GROUP BY order_number
if applied to sample data in your question - output is
As #aleix-cc pointed out, this can be easily done with the TO_JSON function which is currently in preview:
WITH orders as (
SELECT "001" as order_number, "ABC" as product, 1 as quantity UNION ALL
SELECT "001", "DEF", 2 UNION ALL
SELECT "002", "GHI", 1
)
SELECT
order_number,
TO_JSON(ARRAY_AGG(STRUCT(product, quantity))) json_value
FROM orders
GROUP BY order_number
Edit: Since this is a function in preview, you should go with Mikhail's answer and use TO_JSON_STRING.

Pull column value from second to last row

I'm stuck in a loop of figuring out a game plan for this in SQL. Below is my sample data. I'm trying to create another column called "Starting Balance" which would be the amount in "Ending Balance" for the previous LINE. When I have that, I would only like to display where reason = count and forget about the rest.
I can't even fathom what approach to take and any advice would be appreciated.
Sample Data:
ITEM ID
ITEM
LAST UPDATED
REASON
ENDING BALANCE
LINE
123
Pencil
9/1/2020
Correction
400
1
123
Pencil
9/2/2020
Correction
450
2
123
Pencil
9/3/2020
Count
500
3
Expected Output:
ITEM ID
ITEM
LAST UPDATED
REASON
Starting Balance
ENDING BALANCE
123
Pencil
9/3/2020
Count
450
500
if "previous LINE" means the row with Lastupdated before current row:
select * from (
select * , lag(ENDING_BALANCE,1,0) over (partition by ItemId order by LASTUPDATED) as Starting Balance
from table
) t where t.REASON = 'count'
I can't bugtest this, but maybe something like:
SELECT
a.ITEM_ID,
a.ITEM,
a.LAST_UPDATED,
"Count" AS REASON,
b.ENDING_BALANCE AS Starting_Balance,
a.ENDING_BALANCE AS ENDING_BALANCE,
FROM table a
LEFT JOIN table b
ON a.ITEM_ID = b.ITEM_ID, a.LINE = b.LINE + 1
Note that we're joining two copies of the same table together here and labeling them a and b.
No clue if you can do ONs like that, but you could also make the join table have a LINE +1 column which you then use to join.

Create a SQL report associating thousands of records

I'm a newbie in Oracle SQL and i'm trying to do the following:
I have a list of products with sales only on a certain weeks of the year.
I'm just triying to create a whole report of sales for the year and fill those weeks with no sales with zeroes, but preserving the product ID as identifier.
Trying to create that report, i'm starting trying to create a table with all the weeks of the year and de product ID, the problem is that there are thousands of products. I'm trying to get something like:
WEEK_YR PRODUCT_ID
------ ----------
2018011 Product 1
2018012 Product 1
...
2018053 Product 1
...
2018124 Product 1
...
2018011 Product 2
2018012 Product 2
...
2018053 Product 2
...
2018124 Product 2
And then just join this table with the sales table per week, putting 0 in those null weeks from that table.
I request your help at creating the first table, i just count with a table with the products ID and other with the list of weeks from last year
Thanks in advance!
I request your help at creating the first table...
You don't need to create a persistent table for that. Since Oracle 9.2 you can use CTEs (Common Table Expressions). In the example below the cte w is the one you are looking for:
with x as ( --- cte that generates numbers from 1 to 52
select 1 as n from dual
union all
select n + 1 from x where n < 52
),
w as ( --- cte that generates the week_yr
select 2018000 + n as week_yr from x
)
select -- main query now.
w.week_yr,
p...
from w
left join products p on p.week_yr = w.week_yr
where ...
group by ...
In the query above, the cte x generates numbers from 1 to 52. Then the cte w generates the week_yr values you need.
Finally, the main query can do what you want.

Sum nr of sales on a typical article number SQL

it's pretty simple i guess but i can't get it to work.
I have a Sales table with theese columns
Date,Artnr,Amount
For example
20150326, 19929, 2
20150326, 10231, 1
20150326, 10001, 3
20150325, 19929, 4
Now i want to make a SQL that gives me the Artnr and the sum Amount back.So in the example above i sold 6 artnr 19929 at two different times. Now i want to sum the amount on the rows with the same artnr and add them togheter. Like this.
10231, 1
10001, 3
19929, 6
The closest i get is with this SQL
SELECT a.artnr (SELECT SUM(b.amount) FROM SALES b WHERE b.artnr = a.artnr)
FROM SALES a
My Problem here is that i still get all rows back but at least it gives me the right sum amount.
19929, 6
10231, 1
10001, 3
19929, 6
Can someone help me with this please.
Just use group by:
SELECT artnr, SUM(amount)
FROM SALES s
GROUP BY artnr;

Adding a percent column to MS Access Query

I'm trying to add a column which calculates percentages of different products in MS Access Query. Basically, this is the structure of the query that I'm trying to reach:
Product |
Total |
Percentage
Prod1 |
15 |
21.13%
Prod2 |
23 |
32.39%
Prod3 |
33 |
46.48%
Product |
71 |
100%
The formula for finding the percent I use is: ([Total Q of a Product]/[Totals of all Products])*100, but when I try to use the expression builder (since my SQL skills are basic) in MS Access to calculate it..
= [CountOfProcuts] / Sum([CountOfProducts])
..I receive an error message "Cannot have aggregate function in GROUP BY clause.. (and the expression goes here)". I also tried the option with two queries: one that calculates only the totals and another that use the first one to calculate the percentages, but the result was the same.
I'll be grateful if someone can help me with this.
You can get all but the last row of your desired output with this query.
SELECT
y.Product,
y.Total,
Format((y.Total/sub.SumOfTotal),'#.##%') AS Percentage
FROM
YourTable AS y,
(
SELECT Sum(Total) AS SumOfTotal
FROM YourTable
) AS sub;
Since that query does not include a JOIN or WHERE condition, it returns a cross join between the table and the single row of the subquery.
If you need the last row from your question example, you can UNION the query with another which returns the fabricated row you want. In this example, I used a custom Dual table which is designed to always contain one and only one row. But you could substitute another table or query which returns a single row.
SELECT
y.Product,
y.Total,
Format((y.Total/sub.SumOfTotal),'#.##%') AS Percentage
FROM
YourTable AS y,
(
SELECT Sum(Total) AS SumOfTotal
FROM YourTable
) AS sub
UNION ALL
SELECT
'Product',
DSum('Total', 'YourTable'),
'100%'
FROM Dual;