pivot function in Bigquery for transpose, wrong value falling in - sql

I'm trying to use pivot function to transpose rows however action_type=4 keeps falling to the wrong column after I ran my query. Below is the sample data:
SessionId
action_type
products
122
3
5
122
4
1
127
3
2
189
4
1
Ideal output will look like below:
SessionId
action_type_1
products_1
action_type_2
products_2
122
3
5
4
1
127
3
2
189
4
1
I have written below query trying to do the transpose:
select * from
(select * except (SessionId),
max(SessionId) over win SessionId,
row_number() over (win order by SessionId, action_type, products) tab
from
`xxx.sample.xxx`
window win as (partition by SessionId)
)
pivot (
any_value (action_type) as action_type ,
any_value(products) as products for tab in (1,2))
However this output has returning some strange results, for example I see value 4 under action_type_1, which is not what I expected. action_type_1 should only have value 3 because I wanted to define action_type_1=3 and action_type_2=4. Can anyone help look at my query? Any advises are appreciated!

I think, below is what you are looking for
select * from your_table
pivot (
any_value (action_type) as action_type ,
any_value(products) as products
for action_type in (3,4)
)
with output
so, as you can see - instead of relying on offset - you just simply go directly off of action type!
In case if for some reason you need output as _1 and _2 - use below trick
select * from your_table
pivot (
any_value (action_type) as action_type ,
any_value(products) as products
for case action_type when 3 then 1 when 4 then 2 end in (1,2)
)
with output

Related

Snowflake: Repeating rows based on column value

How to repeat rows based on column value in snowflake using sql.
I tried a few methods but not working such as dual and connect by.
I have two columns: Id and Quantity.
For each ID, there are different values of Quantity.
So if you have a count, you can use a generator:
with ten_rows as (
select row_number() over (order by null) as rn
from table(generator(ROWCOUNT=>10))
), data(id, count) as (
select * from values
(1,2),
(2,4)
)
SELECT
d.*
,r.rn
from data as d
join ten_rows as r
on d.count >= r.rn
order by 1,3;
ID
COUNT
RN
1
2
1
1
2
2
2
4
1
2
4
2
2
4
3
2
4
4
Ok let's start by generating some data. We will create 10 rows, with a QTY. The QTY will be randomly chosen as 1 or 2.
Next we want to duplicate the rows with a QTY of 2 and leave the QTY =1 as they are.
Obviously you can change all parameters above to suit your needs - this solution works super fast and in my opinion way better than table generation.
Simply stack SPLIT_TO_TABLE(), REPEAT() with a LATERAL() join and voila.
WITH TEN_ROWS AS (SELECT ROW_NUMBER()OVER(ORDER BY NULL)SOME_ID,UNIFORM(1,2,RANDOM())QTY FROM TABLE(GENERATOR(ROWCOUNT=>10)))
SELECT
TEN_ROWS.*
FROM
TEN_ROWS,LATERAL SPLIT_TO_TABLE(REPEAT('hire me $10/hour',QTY-1),'hire me $10/hour')ALTERNATIVE_APPROACH;

Running Balance/Total on 2 columns

I have the following Table in Azure MSSQL:
ID,
Charge,
Payment
ID is the Primary Key and unique, Charge and Payment are Numeric.
ID charge payment
1 10 null
2 null 10
3 40 null
4 null 30
I want to do the following query:
select *,
SUM(charge)-sum(payment) OVER (order by id) AS Balance
from Table T
order by id asc
Which in the above data sample would look like this:
ID charge payment balance
1 10 null 10
2 null 10 0
3 40 null 40
4 null 30 10
However that query fails, complaining I need to do add a Group by clause, however if I run the following
select *,
SUM(charged) OVER (order by id) AS totalCharged
from table
order by id
That works fine - I feel like I've missed something obvious.
I should also note there are other columns that are in the final query but are omitted from here since they aren't relevant to the logic.
As it turns out, I was missing something obvious.
I changed the source query to use 0 instead of Null and then did the following:
select *,
SUM(charged - payment) OVER (order by id) AS balance
from table
order by id
So figured it out myself whilst thinking upon the porcelein throne.

Querying Data Backward in ORACLE SQL

I have a simple question regarding oracle sql. So i have this table
WEEKNUM DATA
1 10
2 4
3 6
4 7
So i want to make a view that shows like this,
WEEKNUM DATA ACCUM_DATE
1 10 10
2 4 14
3 6 20
4 7 27
I spend hours on this simple one but couldnt get any luck
thanks a lot
SELECT weeknum,
data,
sum(data) over (order by weeknum) accum_data
FROM your_table_name
should work. I'm using the sum analytic function here and assuming that you want to start with the smallest weeknum value and keep increasing the running total as the weeknum values increase. I'm also assuming that you never want to reset the accumulated sum. If you're trying to do something like generating an accumulated sum that restarts each year, you'd want to add a partition by to the analytic function.
You could use a Cross JOin in this case
Query:
select
A.WEEKNUM
, A.DATA
, SUM(B.DATA) DA
from table1 A
cross join table1 B
WHERE A.WEEKNUM>=B.WeekNUM
GROUP BY A.WEEKNUM
, A.DATA
order by A.WEEKNUM
Result:
WEEKNUM DATA DA
1 10 10
2 4 14
3 6 20
4 7 27
Thanks guys but i just found out this method works perfectly,
OVER (ORDER BY WEEKNUM ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CUMULATIVE_WEIGHT
Or use a sub-select to calculate:
select WEEKNUM, DATA, (select sum(DATA) from tablename t2
where t2.weeknum <= t1.weeknum) as ACCUM_DATE
from tablename t1

Select unique records [duplicate]

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Closed 2 years ago.
I'm working with a table that has about 50 colums and 100,000 rows.
One column, call it TypeID, has 10 possible values:
1 thourgh 10.
There can be 10,000 records of TypeID = 1, and 10,000 records of TypeID = 2 and so one.
I want to run a SELECT statement that will return 1 record of each distinct TypeID.
So something like
TypeID JobID Language BillingDt etc
------------------------------------------------
1 123 EN 20130103 etc
2 541 FR 20120228 etc
3 133 FR 20110916 etc
4 532 SP 20130822 etc
5 980 EN 20120714 etc
6 189 EN 20131009 etc
7 980 SP 20131227 etc
8 855 EN 20111228 etc
9 035 JP 20130615 etc
10 103 EN 20100218 etc
I've tried:
SELECT DISTINCT TypeID, JobID, Language, BillingDt, etc
But that produces multiple TypeID rows of the same value. I get a whole bunch of '4', '10', and so on.
This is an ORACLE Database that I'm working with.
Any advise would be greatly appreciated; thanks!
You can use ROW_NUMBER() to get the top n per group:
SELECT TypeID,
JobID,
Language,
BillingDt,
etc
FROM ( SELECT TypeID,
JobID,
Language,
BillingDt,
etc,
ROW_NUMBER() OVER(PARTITION BY TypeID ORDER BY JobID) RowNumber
FROM T
) T
WHERE RowNumber = 1;
SQL Fidle
You may need to change the ORDER BY clause to fit your requirements, as you've not said how to pick one row per TypeID I had to guess.
WITH RankedQuery AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY TypeID ORDER BY [ordercolumn] DESC) AS rn
FROM [table]
)
SELECT *
FROM RankedQuery
WHERE rn = 1;
This will return the top row for each type id, you can add an order by if you want a specific row, not just any.

SQL query for dynamic insert row

I am having data like:
ItemCode Attribute PositionID
ITEM-000032 CHESTSIZE 1
ITEM-000032 JACKETLEN 2
ITEM-000042 CHESTSIZE 1
ITEM-000042 JACKETLEN 2
**ITEM-000049 SLACKWAIST 1**
ITEM-000071 CHESTSIZE 1
ITEM-000071 JACKETLEN 2
ITEM-000074 CHESTSIZE 1
ITEM-000074 JACKETLEN 2
In above data except ITEM-000049 others are having perfect combination. so i want to create a new row for ITEM-000049
As
ITEM-000049 -- 2
to make it perfect.
Kind regards,
Om
Sounds like for each ItemCode, you are expecting 2 records, for 2 different Attributes.
So something like this is what I think you're after. Just run the SELECT part of it first without the INSERT to check it is indeed what you're after.
INSERT YourTable (ItemCode, Attribute, PositionID)
SELECT t.ItemCode, 'SECOND ATTRIBUTE', 2
FROM
(
SELECT ItemCode
FROM YourTable
GROUP BY ItemCode
HAVING COUNT(*) = 1
) t