Is there a dynamic way in BigQuery to select/create columns with pattern? - select

Not sure how to sure how to best phrase it, but essentially I need ~50 columns x 12 weeks in BigQuery and was hoping there was a way to do it more efficiently using some sort of logic or function.
I can generate the script in Python, but the end output itself is long and unwieldy. Is there a cleaner way to do it within BigQuery itself?
Example code:
select id,
sum(case when first_week_flag then visit else 0 end) as sum_visit_first_week,
sum(case when second_week_flag then visit else 0 end) as sum_visit_second_week,
... for 12 weeks,
avg(case when first_week_flag then gap else 0 end) as avg_gap_first_week,
avg(case when second_week_flag then gap else 0 end) as avg_gap_second_week,
... for 12 weeks,
etc. for 50 columns
from table
group by id
Potential for simplification:
select id,
sum(case when {WEEK}_flag then visit else 0 end) as sum_visit_{WEEK},
avg(case when {WEEK}_flag then gap else 0 end) as avg_gap_{WEEk},
etc. for 50 columns
from table
group by id
Can anyone point me in the right direction of what to search for? Thanks!

Related

Postgresql how to group the values in on column of a table and transpose the unique values of another column in the same table, and sum up the rows

I am new to SQL in general, hence this problem is a little tricky to me. I have a table like the example below:
Input Values:
And, I wish to get the following output:
Output Result:
Honestly, I have no idea how to begin to solve this problem. I would appreciate a hint and/or an example solution from anyone. Thank you in advance.
You can perform conditional aggregation and then use a ROLLUP.
For example:
select
velocity,
sum(case when volume = 'VERY HIGH' then sales else 0 end) as very_high,
sum(case when volume = 'HIGH' then sales else 0 end) as high,
sum(case when volume = 'MEDIUM-HIGH' then sales else 0 end) as medium_high,
sum(case when volume = 'LOW' then sales else 0 end) as low,
sum(case when volume = 'VERY LOW' then sales else 0 end) as very_low,
sum(sales) as total
from t
group by rollup (velocity)
order by velocity

Postgres: Extracting the IDs and names of people who are cheating the system

I have a table A with the following transaction data:
ID Name Type
1 Albert Rewards
2 Albert Visit
3 Ruddy Rewards
4 Ruddy Visit
5 Ruddy Purchase
6 Mario Rewards
7 Mario Visit
...
I want a table that only select the rows with names of people who used the "Rewards" and "Visit" type but didn't make a purchase, something like this:
ID Name Type
1 Albert Rewards
2 Albert Visit
6 Mario Rewards
7 Mario Visit
...
Any ideas?
The below query will count for every Visit/Rewards/Purchase how often they happened for a given name - and if the respective results are 1/1/0 then all records from the table with that name will be returned.
If fine-tuning is required (such as cases where the count of any of those > 1 etc.) that can be done by fiddling with the numbers in the 'having' clause. The same is true for adding additional categories to check against.
select *
from mytable a
where exists (select b.name,
sum(case when b.type='Rewards' then 1 else 0 end),
sum(case when b.type='Visit' then 1 else 0 end),
sum(case when b.type='Purchase' then 1 else 0 end)
from mytable b
where b.name=a.name
group by b.name
having sum(case when b.type='Rewards' then 1 else 0 end) = 1
and
sum(case when b.type='Visit' then 1 else 0 end) = 1
and
sum(case when b.type='Purchase' then 1 else 0 end) = 0);
For completion sake: SQLFiddle with 2 queries First query also works, but a little differently

4 weeks or accounting month grouping in postgresql

I have a requirement to group data in transaction table into 4 week groups, or accounting month grouping, any suggestions on how to approach it on postgresql
Regards
SELECT sum(ITEM_C._demand) AS aggre_demand,ITEM_C._week as account_month FROM (SELECT sum(quantity) AS _demand,( CASE WHEN floor((extract(doy from shipment_date)-1)/7)+1 > 0 AND floor((extract(doy from shipment_date)-1)/7)+1 <=4 THEN 1
ELSE (CASE WHEN floor((extract(doy from shipment_date)-1)/7)+1 >4 AND floor((extract(doy from shipment_date)-1)/7)+1 <=8 THEN 2 ELSE 3 END ) END)AS _week, date_trunc('year',shipment_date) AS _Year
FROM smp.shipment
GROUP BY floor((extract(doy from shipment_date)-1)/7)+1,date_trunc('year',shipment_date)) AS ITEM_C
GROUP BY ITEM_C._week, ITEM_C._Year
I think this is not the idle way to do this, as i need to repeat this 1..52 weeks total 13 times
use date_trunc
https://www.postgresql.org/docs/9.1/static/functions-datetime.html
Anything more than this will need some more information. copy some examples and anything you have tried already.
SELECT date_trunc('week', your_date_field)
FROM your_table_name
GROUP BY 1

Using field alias in MSQuery does not work with DB2

This query works in data studio, but fails to show alias in MS Query!
I have tried different types such as "",'',[] and even https://support.microsoft.com/en-us/kb/298955
SELECT 'TRANIN'AS NAME, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150603 AND 20150601 THEN 1 else 0 END) AS CurrentMonth, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150501 AND 20150531 THEN 1 else 0 END) AS LastMonth
FROM ALT3
MS broke MS query a long time ago...
I've tried to get it to work right, but nothing worked. I've pretty much given up.
Normally I just rename the column once the data is back in Excel.
But if you really want the name returned from MS query, this works:
WITH tbl AS (SELECT 'TRANIN'AS NAME
, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150603 AND 20150601
THEN 1 else 0 END) AS CurrentMonth
, SUM(CASE WHEN ALT3.TRANINDT BETWEEN 20150501 AND 20150531
THEN 1 else 0 END) AS LastMonth
FROM ALT3)
SELECT * FROM TBL

Union Statement that can be changed to Case statement

Good Day Everyone!
well i have this kind of code and it kinda ugly,
a friend of mine told me i can implement Case Statements in here, but i do not know how or how would i implement, the code is long so if you could just help me to optimize my code i would appreciate it greatly!
PS. please be gentle to me, im new in T-sql :)
Thank yoU!
SELECT
SUM(CYJEWELRY) 'CY_Jewelry'
,SUM(CYAPPLICANCE) 'CY_Appliance'
,SUM(CYCELLPHONE) 'CY_Cellphone'
,SUM(PYJEWELRY) 'PY_Jewelry'
,SUM(PYAPPLIANCE) 'PY_Appliance'
,SUM(PYCELLPHONE) 'PY_Cellphone'
FROM
(
---TOTAL NUNG A FORMAT 0,0,0,0,0,0
--------------CURRENT YEAR JEWELRY
SELECT COUNT (*) AS CYJEWELRY,0 AS CYAPPLICANCE,0 AS CYCELLPHONE,0 AS PYJEWELRY,0 AS PYAPPLIANCE,0 AS PYCELLPHONE
FROM #TEMPTABLE1
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------CURRENT YEAR APPLIANCE
SELECT 0,COUNT(*),0,0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 1
UNION
------------CURRENT YEAR CELLPHONE
SELECT 0,0,COUNT(*),0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 2
UNION
---------------LAST YEAR JEWELRY
SELECT 0,0,0,COUNT(*),0,0
FROM #TEMPTABLE2
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------------------LAST YEAR APPLIANCE
SELECT 0,0,0,0,COUNT (*),0
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 1
UNION
-------------------------LAST YEAR CELLPHONE
SELECT 0,0,0,0,0,COUNT(*)
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 2
)A
Assuming your data is bit like this Sql Fiddle Example, try this for the sub query using SUM() and CASE.
SELECT SUM(CASE WHEN fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14 ELSE 0 END) Col1And4,
SUM(CASE WHEN fld_StorageGroupID = 1 THEN 1 ELSE 0 END) Col2And5,
SUM(CASE WHEN fld_StorageGroupID = 2 THEN 1 ELSE 0 END) Col3And6
FROM #TEMPTABLE1
GROUP BY fld_StorageGroupID
Since you are applying the same filter for last 3 columns in the subquery, I have done only first 3 columns here.
EDIT:
I think this is better than above (Note: no need to use SUM() in the main query).
Fiddle Example with data
select col1_4 CY_Jewelry,
col2_5 CY_Appliance,
col3_6 CY_Cellphone,
col1_4 PY_Jewelry,
col2_5 PY_Appliance,
col3_6 PY_Cellphone
from (
select sum(case when id>= 3 and id <= 14 then 1 else 0 end) col1_4,
sum(case when id = 2 then 1 else 0 end) col2_5,
sum(case when id = 3 then 1 else 0 end) col3_6
from t
--group by id
) X