Transforming table - sql

I have a table like this
Type, Year, Month, Sales
I want to split the Type columns to several columns and transform the table to
year, month , type A sales, type B sales, type C sales
We actually dont know the number of type we have as well

Related

SQL How to add a column to a table that's the sum of a category's quantity

I have a data table shaped like below:
What I'm looking to do with SQL is add a column that will be the sum for the total category by month without removing any rows. For Example,
My goal is to take this category data and do some calculations with it like dividing it by the Qty and seeing how it changes over time.
What I've tried to do is use GROUP BY the category and date but that ends up with me losing the Item level data which I want to compare the Category level data to.
I also tried doing something like this
SELECT
Item, Category, Date, Qty, (sum(QTY) from TABLE)
FROM TABLE
but that only gives the sum of the QTY for the whole column not split out by Month/Year and Category.
Does anyone know what might help? I'm relatively new to using SQL so I hope I explained my question properly.
Use window functions:
select t.*,
sum(qty) over (partition by category, date) as category_sum
from t;
This assumes that date is really just the month and year. If it is the exact date, you need to extract the month and year from it.

Return defined number of unique values in separate columns all meeting same 'Where' Criteria

We enter overrides based on a unique value from our tables (we have two columns with unique values for each transaction, so may or may not be primary key).
Sometimes we have to enter multiple overrides based on the same set of criteria, so it would be nice to be able to pull multiple unique values in one query that all meet the same criteria in the where clause as our system throws a warning if the same unique id is used for more than one override.
Say we have some customers that were under charged for three months and we need to enter a commission override for each of the three sales people that split the accounts for each month:
I've tried the following code, but the same value gets returned for each column:
select month, customer, product, sum(sales),
any_value(unique_id)unique_id1,
any_value(unique_id)unique_id2,
any_value(unique_id)unique_id3
from table
where customer in (j,k,l) and product = m and year = o
group by 1,2,3;
This will give me a row for each month and customer, but the values in unique_id1, unique_id2 and unique_id3 are the same on each row.
I was able to use:
select month, customer, product, sum(sales),
string_agg(unique_id, "," LIMIT 3)
from table
where customer in (j,k,l) and product = m and year = o
group by 1,2,3;
and split the unique_ids in a spreadsheet but I feel there has to be a better way to accomplish this directly in SQL.
I figure I could use a sub query and select column based on row 1,2,3, but I'm trying to eliminate the redundancy of including the same 'where' criteria in the sub query.
Beow is for BigQuery Standard SQL
I think you second query was close enough to get to something like below
#standardSQL
SELECT month, customer, product, sales,
arr[OFFSET(0)] unique_id1,
arr[SAFE_OFFSET(1)] unique_id2,
arr[SAFE_OFFSET(2)] unique_id3
FROM (
SELECT month, customer, product, SUM(sales) sales,
ARRAY_AGG(unique_id ORDER BY month DESC LIMIT 3) arr
FROM `project.dataset.table`
WHERE customer IN ('j','k','l') AND product = 'm' AND year = 2019
GROUP BY month, customer, product
)

How do I use array_agg with a condition?

I have a table with a list of potential customers, their activity, and their sales representative. Every customer can have up to 1 sales rep. I've built a summary table where I aggregate the customer activity, and group it by the sales rep, and filter by the customer creation date. This is NOT a cohort (the customers do not all correspond to the scheduled_flights, but rather this is a snapshot of activity for a given period of time) It looks something like this:
Now, in addition to the total number of customers, I'd also like to output an array of those actual customers. The customers field is currently calculated by performing sum(is_customer) as customers and then grouping by the sales rep. To build the array, I've tried to do array_agg(customer_name) which outputs the list of all customer names -- I just need the list of names who also satisfy the condition that is_customer = 1, but I can't use that as a where clause since it would filter out other activity, like scheduled and completed flights for customers that were not new.
This should probably work:
array_agg(case when is_customer = 1 then customer_name end) within group (order by customer_name)
Snowflake should ignore NULL values in the aggregation.

Populating fact table

I've a data warehouse for sales, it has 3 dimensions [product,time,store] and a fact table [sales_fact].
Primary key of 'sales_fact' table is made up of all primary keys of dimensions table, dimension tables are all filled up manually now I want to fill 'sales_fact' table with SUM of prices of products stored in a city for a specific month or 3 month period.
How should I sum up prices from product table which are related to a specific month and add it to fact table?
Considering that sum up prices from product table which are related to a specific month
is a measure, your query can be like below :
SELECT DS.City, DT.[Month], SUM(DP.Price)FROM
SalesFact AS S
LEFT JOIN DimProduct AS DP ON DP.ProductSK=S.ProductSK
LEFT JOIN DimTime AS DT ON DT.DateSK=S.DateSK
LEFT JOIN DimStore AS DS ON DS.StoreSK=S.StoreSK
WHERE [Date condition] --Add your date conditoon
GROUP BY DS.City, DT.[Month]
You can use a view for this measure.

SQL combining GROUP BY and SUM

I need help with SQL. I have an sqlite table like so;
CREATE TABLE mytable (datetime DATE, type TEXT, amount REAL)
I need a query which would sum up amount for each type AND year-month (as you can see the year is also extracted since the data can span several years). I've come to something half-way, but I'm a bit rusty on SQL.
sqlite> SELECT strftime('%Y',datetime) AS year, strftime('%m',datetime) AS month, type, amount FROM mytable ;
2009|06|Type1|-1000.0
2009|06|Type1|-100.0
2009|06|Type2|-100.0
2009|07|Type1|-214.91
2009|07|Type2|-485.0
I've tried a number of combinations of SUM and GROUP BY on my query above but none of them does what I want. What I want is a result something like:
2009|06|Type1|-1100.0
2009|06|Type2|-100.0
2009|07|Type1|-214.91
2009|07|Type2|-485.0
Yes, type should be a foreign key, I simplified things to make it easier to ask the question :)
SELECT strftime('%Y',datetime) AS year,
strftime('%m',datetime) AS month,
type,
Sum(amount) As Amount
FROM mytable
Group By 1, 2, 3
Note
Some DBs don't support group by index so you would have to do this.
SELECT strftime('%Y',datetime) AS year,
strftime('%m',datetime) AS month,
type,
Sum(amount) As Amount
FROM mytable
Group By strftime('%Y',datetime),
strftime('%m',datetime),
type