Good day,
I have three columns: Game_Date, Decision, Record
For each row (Game_Date
You can use a window (analytic Function) to get the total per date/season.
NOW TESTED!:
With GAME as
(Select to_date('15-MAR-15','DD-MON-YY') as Game_date, 'W' as decision, '2014-2015' as Season from dual UNION ALL
Select to_date('19-MAR-15','DD-MON-YY') as Game_date, 'L' as decision, '2014-2015' as Season from dual UNION ALL
Select to_date('22-MAR-15','DD-MON-YY') as Game_date, 'L' as decision, '2014-2015' as Season from dual UNION ALL
Select to_date('24-MAR-15','DD-MON-YY') as Game_date, 'O' as decision, '2014-2015' as Season from dual UNION ALL
Select to_date('28-MAR-15','DD-MON-YY') as Game_date, 'W' as decision, '2014-2015' as Season from dual UNION ALL
Select to_date('01-APR-15','DD-MON-YY') as Game_date, 'W' as decision, '2014-2015' as Season from dual )
--YOU ONLY NEED TO RUN THIS PART!!!
SELECT Game_date AS "Date", Decision,
SUM(CASE WHEN Decision = 'W' THEN 1 else 0 END) Over (partition by Season order by game_Date) || '-' ||
SUM(CASE WHEN Decision = 'L' THEN 1 else 0 END) Over (partition by Season order by game_Date) || '-' ||
SUM (CASE WHEN Decision = 'O' THEN 1 else 0 END) Over (partition by Season order by game_Date) AS "RECORD"
FROM Game
WHERE Season = '2014-2015'
--AND (Team_Visitor_ID = 1 OR Team_Home_ID = 1)
ORDER BY Game_Date desc
try this :
select TO_CHAR(Game_Date, 'DD MON ''YY') AS "DATE",
SUM(W) Over (order by Game_Date) || '-' ||
SUM(L) Over (order by Game_Date) || '-' ||
SUM(O) Over (order by Game_Date) AS "RECORD"
from (
SELECT Game_Date,
SUM (CASE WHEN Decision like 'W' THEN 1 END) as W,
SUM (CASE WHEN Decision like 'L' THEN 1 END) as L,
SUM (CASE WHEN Decision like 'O' THEN 1 END) as O
FROM Game
WHERE Season = '2014-2015' AND (Team_Visitor_ID = 1 OR Team_Home_ID = 1)
GROUP BY Game_Date)
ORDER BY Game_Date DESC;
Related
I have to create a query that shows whether the employees has taken what kind of leave on time card or if they have taken any leave "Vacation".
The output should look like:
SELECT person_number,
Sum(
CASE
WHEN element = 'Overtime' THEN measure
END) AS overtime_measure_hours,
Sum(
CASE
WHEN elements LIKE 'Regular Pay' THEN measure
END) AS regular_measure_hours,
Sum(
CASE
WHEN elements IN ( 'Double_Time' ) THEN measure
END) AS Other_amount,
Max(
CASE
WHEN elements IN ( 'Double_Time' ) THEN 'Double'
END) AS Other_code
(
SELECT papf.person_number,
atrb.attribute_category element,
atrb.measure measure_hours,
rec.start_date,
rec.end_date
FROM per_all_people_f papf,
hwm_tm_rec rec,
fusion.hwm_tm_rep_atrbs atrb,
fusion.hwm_tm_rep_atrb_usages ausage,
hwm_tm_statuses status
WHERE 1=1
AND atrb.tm_rep_atrb_id = ausage.tm_rep_atrb_id
AND ausage.usages_source_id = rec.tm_rec_id
AND ausage.usages_source_version = rec.tm_rec_version
AND status.tm_bldg_blk_id = rec.tm_rec_id
AND status.tm_bldg_blk_version = rec.tm_rec_version
AND rec.tm_rec_type IN ( 'RANGE',
'MEASURE' )
AND papf.person_number = '101928'
AND trunc (status.date_to) = to_date ('31/12/4712', 'DD/MM/YYYY')
--and atrb.attribute_category in( 'Overtime','Regular Pay', 'Double_Time')
AND trunc (sh21.start_time) BETWEEN trunc(:P_From_Date) AND trunc(:P_To_Date) )
GROUP BY person_number
UNION ALL
SELECT person_number,
sum(
CASE
WHEN element = 'Overtime' THEN measure
END) AS overtime_measure_hours,
sum(
CASE
WHEN elements LIKE 'Regular Pay' THEN measure
END) AS regular_measure_hours,
sum(
CASE
WHEN absence_name IN ( 'Vacation' ) THEN abs_duration
END) AS Other_amount,
max(
CASE
WHEN absence_name IN ( 'Vacation' ) THEN absence_name
END) AS Other_code
(
SELECT papf.person_number,
atrb.attribute_category element,
atrb.measure measure_hours,
rec.start_date,
rec.end_date,
abs.NAME absence_name,
abs.duration abs_duration
FROM per_all_people_f papf,
hwm_tm_rec rec,
fusion.hwm_tm_rep_atrbs atrb,
fusion.hwm_tm_rep_atrb_usages ausage,
hwm_tm_statuses status,
anc_absence_types_vl abs
WHERE 1=1
AND atrb.tm_rep_atrb_id = ausage.tm_rep_atrb_id
AND ausage.usages_source_id = rec.tm_rec_id
AND ausage.usages_source_version = rec.tm_rec_version
AND status.tm_bldg_blk_id = rec.tm_rec_id
AND status.tm_bldg_blk_version = rec.tm_rec_version
AND rec.tm_rec_type IN ( 'RANGE',
'MEASURE' )
AND papf.person_number = '101928'
AND trunc (status.date_to) = to_date ('31/12/4712', 'DD/MM/YYYY')
--and atrb.attribute_category in( 'Overtime','Regular Pay', 'Double_Time')
AND trunc (sh21.start_time) BETWEEN trunc(:P_From_Date) AND trunc(:P_To_Date)
AND abs.absence_type_id = atrb.absence_type_id )
GROUP BY person_number
Although these queries are working separately it is not working with group by on each subquery.
If I merge the two queries, the issue I am having is with Other_code & other_amount. These columns have values from two different tables.
How can I solve this?
Output should be returned for the two dates p_from_date- 01-Jan-2021 and p_to_date- 31-Jul-2021 as:
Person_Number Overtime_measure_hours Regular_Measure_hours Other_code Other_amount
101928 18 15 Double_Time 34
101928 18 15 Vacation 1
i.e. Overtime_measure_hours, Regular_Measure_hours and Other_amount should have the sum of these values.
Please help me with the BigQuery query. I need to build a closed funnel of user steps events in a mobile app for a week.
The table looks like this:
It is necessary to collect all unique users who have passed from step 1 to step 2 and so on to step 6 during this period. Between these steps, they could do something else, be distracted by other events. But what is important is the passage of each unique user through these steps in a given period of time.
Please tell me how to create such a funnel?
There can be multiple ways of achieving this. Here is an approach using identical sample data, which is not the most optimal but is very self-explanatory and definite:
with data as (
select 'a' as user_id, cast('2020-01-01 04:45:00' as timestamp) as event_timestamp, '1' as step_name
union all
select 'b' as user_id, cast('2020-01-01 04:50:00' as timestamp) as event_timestamp, '1' as step_name
union all
select 'a' as user_id, cast('2020-01-01 05:00:00' as timestamp) as event_timestamp, '2' as step_name
union all
select 'a' as user_id, cast('2020-01-01 05:15:00' as timestamp) as event_timestamp, '3' as step_name
union all
select 'b' as user_id, cast('2020-01-01 04:55:00' as timestamp) as event_timestamp, '2' as step_name
union all
select 'c' as user_id, cast('2020-01-01 04:58:00' as timestamp) as event_timestamp, '1' as step_name
union all
select 'a' as user_id, cast('2020-01-01 05:16:00' as timestamp) as event_timestamp, '4' as step_name
union all
select 'b' as user_id, cast('2020-01-01 05:16:00' as timestamp) as event_timestamp, '3' as step_name
),
data2 as (
select a.user_id, a.step_name step_1, b.step_name step_2, c.step_name step_3, d.step_name step_4 from ( select user_id, event_timestamp, step_name from data where step_name = '1') a
left join data b on (a.user_id = b.user_id and a.event_timestamp < b.event_timestamp and b.step_name = '2')
left join data c on (b.user_id = c.user_id and b.event_timestamp < c.event_timestamp and c.step_name = '3')
left join data d on (c.user_id = d.user_id and c.event_timestamp < d.event_timestamp and d.step_name = '4')
)
select * from (
select 'step_1' as event_name, count(distinct user_id) as n_users from data2 where step_1 is not null
group by 1
union all
select 'step_2' as event_name, count(distinct user_id) as n_users from data2 where (step_1 is not null and step_2 is not null)
group by 1
union all
select 'step_3' as event_name, count(distinct user_id) as n_users from data2 where (step_1 is not null and step_2 is not null and step_3 is not null)
group by 1
union all
select 'step_4' as event_name, count(distinct user_id) as n_users from data2 where (step_1 is not null and step_2 is not null and step_3 is not null and step_4 is not null)
group by 1
)
order by 1
You can further optimize this based on your specific filters, conditions, etc.
I am using
with t1 as
(
SELECT
DATE_TRUNC(PARSE_DATE("%Y%m%d", date), MONTH) as month,
fullVisitorId,
product.productSKU,
product.v2ProductName,
case when hits.ecommerceaction.action_type = '2' then 1 else 0 end as pdp_visitor,
count(case when hits.ecommerceaction.action_type = '2' then fullvisitorid else null end) AS views_pdp,
count(case when hits.ecommerceaction.action_type = '3' then fullvisitorid else null end) AS add_cart,
count(case when hits.ecommerceaction.action_type = '6' then hits.transaction.transactionid else null end) AS conversions,
count(distinct(hits.transaction.transactionId)) as transaction_id_cnt,
FROM `table` AS nr,
UNNEST(hits) hits,
UNNEST(product) product
GROUP BY 1,2,3,4,5
)
select
month,
sum(views_pdp) as pdp
,sum(add_cart) as add_cart
,sum(conversions) as conversions
,sum(transaction_id_cnt)
from t1
group by 1
order by 1 desc;
Which returns
month pdp add_cart conversions f0_
2021-02-01 500 100 20 10
2021-01-01 600 200 30 20
I know that f0_ ( count(distinct(hits.transaction.transactionId)) ) is bad here because of product.productSKU and product.v2ProductName grouping.
In general, when user makes an order with 3 items in his basket, I want to count this as one order, whereas now it is counted as 3.
This count(distinct(hits.transaction.transactionId)) as transaction_id_cnt results in the correct output if I comment out product.productSKU and product.v2ProductName.
Running this query:
with t1 as
(
SELECT
DATE_TRUNC(PARSE_DATE("%Y%m%d", date), MONTH) as month,
fullVisitorId,
-- product.productSKU, # commented out
-- product.v2ProductName, # commented out
case when hits.ecommerceaction.action_type = '2' then 1 else 0 end as pdp_visitor,
count(case when hits.ecommerceaction.action_type = '2' then fullvisitorid else null end) AS views_pdp,
count(case when hits.ecommerceaction.action_type = '3' then fullvisitorid else null end) AS add_cart,
count(case when hits.ecommerceaction.action_type = '6' then hits.transaction.transactionid else null end) AS conversions,
count(distinct(hits.transaction.transactionId)) as transaction_id_cnt,
FROM `table` AS nr,
UNNEST(hits) hits,
UNNEST(product) product
GROUP BY 1,2,3,4,5
)
select
month,
sum(views_pdp) as pdp
,sum(add_cart) as add_cart
,sum(conversions) as conversions
,sum(transaction_id_cnt)
from t1
group by 1
order by 1 desc;
Returns what is expected, but now I don't have productSKU and v2ProductName which I need. I suspect that the problem is that each order is a new line in google big query and when I ask to to select it by product name and SKU, I count the uniques and then sum it.
How can I achieve the correct summation of count(distinct(hits.transaction.transactionId)) without losing the grouping by product.productSKU and product.v2ProductName which explodes this metric?
On the group by Query you could cherry pick them as array(so you don't group by them):
ARRAY_AGG(DISTINCT product.productSKU IGNORE NULLS) AS productSKU_list,
ARRAY_AGG(DISTINCT product.v2ProductName IGNORE NULLS) AS productName_list,
Update per your below comment: If you want to use them in further group by just save them as string instead of array.
STRING_AGG(DISTINCT product.productSKU, ',') AS productSKU_list,
STRING_AGG(DISTINCT product.v2ProductName, ',') AS productName_list,
Hi im habing trouble with a SQL case, the problem is im trying to run a case with 7 different columns, the columns can have different kinds of data (string,date,number) depending on an id.
This means that under some id's the rows in a column will be string while under other ids the rows in a column will be number.
I realise this isn't a conventional use of astructured database, but this specific table serve a specific purpose where this approach was deemed usefull in the past.
The case is supposed to only select a "then" when the column does have a number. However when i run it i get a invalid number ORA-01722. because one of the, rows will hold a string og date.
I realise its properly because oracle asses the sql before executing, and doesnt execute sequential, therefore giving errors on these column even though it wouldn actually have to calculate on the column under a given ID.
The code im trying to execute is the following, The hardcoded 1 and 2 before 'then' will change depending on ctrl_id (the unique id) and it will be the one securing that we only look and a list_val column/row with a number
WITH sampledata1 AS
(SELECT '1' ctrl_id, '23' list_val1, 'Textfield' list_val2
FROM dual),
sampledata2 AS
(SELECT '2' ctrl_id, 'Textfield' list_val1, '45' list_val2
FROM dual),
sampledata3 AS
(SELECT *
FROM sampledata1
UNION
SELECT *
FROM sampledata2)
SELECT CASE
WHEN ctrl_id = 1 THEN
AVG(list_val1)
over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
WHEN ctrl_id = 2 THEN
AVG(list_val2)
over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
END AS avg_val
FROM sampledata3 qd
Any suggestions to how i can make this work. either a workaround or a different approach ?
Thx in advance.
--------- Solution below
I used some of the suggestions and solutions posted below and got this code samble working. I will try and implement it with the system. Thx for the help everyone you saved me alot of headache.
WITH sampledata1
AS (SELECT '1' ctrl_id, '23' list_val1, 'Textfield' list_val2 FROM DUAL),
sampledata2
AS (SELECT '2' ctrl_id, 'Textfield' list_val1, '45' list_val2 FROM DUAL),
sampledata3
AS (SELECT * FROM sampledata1
UNION
SELECT * FROM sampledata2)
select ctrl_id,
avg(CASE WHEN TRIM(TRANSLATE(list_val1, ' +-.0123456789', ' ')) is null
then list_val1 else null end) over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC) list_val1,
avg(CASE WHEN TRIM(TRANSLATE(list_val2, ' +-.0123456789', ' ')) is null
then list_val2 else null end) over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC) list_val2
from sampledata3 qd
You can try to filtered out values with non-numeric symbols with something like
AVG(CASE WHEN TRIM(TRANSLATE(list_val1, ' +-.0123456789', ' ')) is null then list_val1 else null end) OVER (...)
NB! Unfortunately strings like '+12-.3' also will be recognized as a numeric and in this case you will get same ora-01722
The aggregate function like AVG does not work with VARCHAR data type, NUMBER or INTEGER is a must when such functions are being used.
I have modified the query to have number instead of a string,
WITH sampledata1
AS (SELECT '1' ctrl_id, '23' list_val1, '43' list_val2 FROM DUAL),
sampledata2
AS (SELECT '2' ctrl_id, '34' list_val1, '45' list_val2 FROM DUAL),
sampledata3
AS (SELECT * FROM sampledata1
UNION
SELECT * FROM sampledata2)
SELECT CASE
WHEN ctrl_id = 1
THEN
AVG (list_val1)
OVER (PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
WHEN ctrl_id = 2
THEN
AVG (list_val2)
OVER (PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
END
AS avg_val
FROM sampledata3 qd
The output is
AVG_VAL
----------
23
45
Edit 1
Perhaps you can do something like the below to first ascertain row return NUMERIC or NON-NUMERIC.
Change as per your requirements.
WITH sampledata1
AS (SELECT '1' ctrl_id, '23' list_val1, 'Textfield' list_val2 FROM DUAL),
sampledata2
AS (SELECT '2' ctrl_id, 'Textfield' list_val1, '45' list_val2 FROM DUAL),
sampledata3
AS (SELECT * FROM sampledata1
UNION
SELECT * FROM sampledata2),
sampledata4
AS (SELECT LENGTH (TRIM (TRANSLATE (ctrl_id, ' +-.0123456789', ' ')))
ctrl_id,
LENGTH (TRIM (TRANSLATE (list_val1, ' +-.0123456789', ' ')))
list_val1,
LENGTH (TRIM (TRANSLATE (list_val2, ' +-.0123456789', ' ')))
list_val2
FROM sampledata3 qd -- group by ctrl_id
)
( SELECT CASE WHEN ctrl_id IS NULL THEN AVG (ctrl_id) ELSE 0 END ctrl_id,
CASE WHEN list_val1 IS NULL THEN AVG (list_val1) ELSE 0 END list_val1,
CASE WHEN list_val2 IS NULL THEN AVG (list_val2) ELSE 0 END list_val2
FROM sampledata4
GROUP BY ctrl_id, list_val1, list_val2)
Not sure why you are using that Analytic function. For your basic problem this would work:
SELECT AVG(CASE
WHEN ctrl_id = 1 THEN list_val1
WHEN ctrl_id = 2 THEN list_val2
END) AS avg_val
FROM sampledata3 qd
You're trying to get Average sum of list_val1, However list_val1 from sampledata2 query returns VARCHAR value.
You shouldn't use AVG on non-numeric values.
WITH sampledata1 AS
(SELECT '1' ctrl_id, '23' list_val1, '10' list_val2
FROM dual),
sampledata2 AS
(SELECT '2' ctrl_id, '45' list_vall, '90' list_val2
FROM dual),
sampledata3 AS
(SELECT *
FROM sampledata1
UNION
SELECT *
FROM sampledata2)
SELECT CASE
WHEN ctrl_id = 1 THEN
AVG(list_val1)
over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
WHEN ctrl_id = 2 THEN
AVG(list_val2)
over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
END AS avg_val
FROM sampledata3 qd
I have to select query like the following example :
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_12
from price_list_LastYear
UNION ALL
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_11
from price_list_TwoLastYear.
When I execute the query, In my column header I get name, JAN_12, FEB_12.
I want to combine my results like : name, JAN_11, JAN_12, FEB_11,FEB_12.
Try this:
SELECT P1.name,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'01',P1.PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'02',P1.PRICE)) FEB_12,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'01',P2.PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'02',P2.PRICE)) FEB_11
FROM price_list_LastYear P1
JOIN price_list_TwoLastYear P2
ON P1.nmae = P2.nmae
GROUP BY P1.nmae
If same name doesn't exists in both tables try this:
SELECT N.name,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'01',P1.PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'02',P1.PRICE)) FEB_12,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'01',P2.PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'02',P2.PRICE)) FEB_11
FROM
(
SELECT name FROM price_list_LastYear
UNION
SELECT name FROM price_list_TwoLastYear
) N
LEFT JOIN price_list_LastYear P1
ON N.nmae = P1.name
LEFT JOIN price_list_TwoLastYear P2
ON N.nmae = P2.name
GROUP BY N.name
Try this
SELECT A.*, B,JAN_11, B.FEB_11 FROM (
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_12
from price_list_LastYear
Group By Name) A
LEFT OUTER JOIN (
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_11
from price_list_TwoLastYear
Group By Name) B ON A.name = B.Name
Or
Select name,
SUM(CASE WHEN Yr = '11' THEN DECODE(Mnth,'01',PRICE) ELSE NULL END) JAN_11,
SUM(CASE WHEN Yr = '12' THEN DECODE(Mnth,'01',PRICE) ELSE NULL END) JAN_12,
SUM(CASE WHEN Yr = '11' THEN DECODE(Mnth,'02',PRICE) ELSE NULL END) FEB_11,
SUM(CASE WHEN Yr = '12' THEN DECODE(Mnth,'02',PRICE) ELSE NULL END) FEB_12
from
(
SELECT '12' As yr, name, TO_CHAR(Datee,'MM') Mnth, Price
FROM price_list_LastYear
UNION ALL
SELECT '11' As yr, name, TO_CHAR(Datee,'MM') Mnth, Price
FROM price_list_TwoLastYear
)
GROUP BY Name
If the name does not exist in both tables, then it might be difficult to use a JOIN. So here is a version using UNION ALL and then applying an aggregate function with a CASE expression to transform the data to columns:
SELECT name,
sum(case when Month = 'JAN_12' then price else 0 end) JAN_12,
sum(case when Month = 'FEB_12' then price else 0 end) FEB_12,
sum(case when Month = 'JAN_11' then price else 0 end) JAN_11,
sum(case when Month = 'FEB_11' then price else 0 end) FEB_11
FROM
(
Select name,
PRICE,
case
when TO_CHAR(Datee,'MM') = '01' Then 'JAN_12'
when TO_CHAR(Datee,'MM') = '02' Then 'FEB_12' End Month
from price_list_LastYear
WHERE TO_CHAR(Datee,'MM') in ('01', '02')
UNION ALL
Select name,
PRICE,
case
when TO_CHAR(Datee,'MM') = '01' Then 'JAN_11'
when TO_CHAR(Datee,'MM') = '02' Then 'FEB_11' End Month
from price_list_TwoLastYear
WHERE TO_CHAR(Datee,'MM') in ('01', '02')
) src
GROUP BY name