Disclaimer...I'm a Noob
I am writing a query from CampaignStats table that aggregates based on a stripped campaign label. The query returns correct values for all metrics except Impressions and Cost. No matter what I've tried so far, this figure still doesn't match. Here are the totals for two of my campaigns from yesterday (June 17th):
CampaignStats:
Date label Impressions cost clicks avg_cpc
6/17/2022 sat_brand 2687 140.472666 15 9.3648444
CampaignBasicStats:
Date label Impressions cost clicks avg_cpc
6/17/2022 sat_brand 699 152.620961 15 10.17473073
Utilizing the CampaignBasicStats table, I receive aggregated totals for all metrics that match the UI, including Impressions and Cost. The issue is there are metrics in CampaignStats and getting some illumination/information on what I may not be doing correct, will help in the future.
I did a JOIN with the Campaign table originally; the below query refers to a permanent table that I pulled out separately in case this was a cause of the discrepancy.
Code Below:
SELECT
cs.Date,
EXTRACT(ISOWEEK FROM cs.DATE) AS isoweek,
cl.label,
(SUM(cs.Cost) / 1000000) AS cost,
SUM(cs.Clicks) AS clicks,
CASE WHEN SUM(Clicks)=0 OR SUM(Cost)=0 THEN 0 ELSE
((SUM(Cost)/SUM(Clicks))/1000000) END AS avg_cpc,
SUM(cs.Impressions) AS Impressions,
CASE WHEN SUM(cs.Clicks)=0 THEN 0 ELSE
(SUM(cs.Clicks)/SUM(cs.Impressions)) END AS ctr,
SUM(cs.Conversions) as conversions,
CASE WHEN SUM(cs.Conversions)=0 OR SUM(cs.Clicks)=0 THEN 0 ELSE
(SUM(cs.Conversions)/SUM(cs.Clicks)) END AS cvr,
CASE WHEN SUM(cs.Conversions)=0 OR SUM(cs.Cost)=0 THEN 0 ELSE
(SUM(cs.Cost)/SUM(cs.Conversions))/1000000 END AS cost_per_conversion
FROM
`bold-quanta-######.######_google_ads_dataset.CampaignStats_##########` cs
JOIN
`bold-quanta-######.queried_permanent_tables.process_campaign_labels` cl
ON
cs.CampaignId = cl.CampaignId
GROUP BY
1, 2, 3
Related
I want to calculate customer retention week over week. My sales_orders table has columns order_date, and customer_name. Basically I want to check if a customer in this week also had an order the previous week. To do this, I have used CASE WHEN and subquery as follows (I have extracted order_week in a cte I've called weekly_customers and gotten distinct customer names within each week):
SELECT wc.order_week,
wc.customer,
CASE
WHEN wc.customer IN (
SELECT sq.customer
FROM weekly_customers sq
WHERE sq.order_week = (wc.order_week - 1))
THEN 'YES'
ELSE 'NO'
END AS present_in_previous_week
from weekly_customers wc
The query returns the correct data. My issue, the table is really huge with about 15000 distinct weekly values. This obviously leads to very long execution time. Is there a way I can improve this loop or even an alternative to the loop altogether?
Something like this:
SELECT
wc.order_week,
wc.customer,
CASE WHEN wcb.customer IS NOT NULL THEN "YES" ELSE "NO" END AS present_in_previous_week
FROM weekly_customers AS wca
LEFT JOIN
weekly_customers AS wcb
ON
wca.customer = wcb.customer
AND wca.order_week - 1 = wcb.order_week
This joins all of the customer data onto the customer data from a week ago. If there is a record for a week ago then wcb.customer will not be null, and we can set the flag to "YES". Otherwise, we set the flag to "NO".
Sorry if this sounds very basic; bear with me.
I need to determine the conversion rate of 3 ads, each representing a product; that would be subscription divided by the number of people who clicked the ad.
COLUMNS:
person_id - unique identifier of the person
date - date they were shown the ad
ad_id - content of the ad: ad_1_product1, ad_2_product2, or ad_3_product3
clicked (TRUE/FALSE) - clicked on the ad
signed_up - (TRUE/FALSE) created an account
subscribed (TRUE/FALSE) - started a paid subscription
I set clicked, signed_up and subscribed as boolean.
MY CODE:
SELECT ad_id, (count(subscribed) / count(clicked)) as CR
FROM videoadcampaign
WHERE subscribed = 'TRUE' AND clicked = 'TRUE'
GROUP BY ad_id;
Of course, the code above gives me a ratio of 1, because SQL is still counting the total and dividing by the same number because of those conditions.
I am totally stuck.
I will also need to calculate other KPIs for clicks and signed_up, so filtering those booleans and put them into a ratio is the core of what I need to do.
Is there a way I can tell SQL to compute CR = SUBS (TRUE) / SUBS (TRUE + FALSE) [or total count] and then filter by CLICK = TRUE?
Thank you tons for your help!
It depends on your database, but the general notion would be:
SELECT ad_id,
(SUM(CASE WHEN subscribed = 'TRUE' THEN 1.0 ELSE 0 END) /
SUM(CASE WHEN clicked = 'TRUE' THEN 1 ELSE 0 END)
) as CR
FROM videoadcampaign
GROUP BY ad_id;
In many databases, you can do something like this if the columns are integers (0 = false, 1 = true):
SELECT ad_id, SUM(subscribed) / SUM(clicked) as CR
FROM videoadcampaign
WHERE clicked = 'TRUE'
GROUP BY ad_id;
Or even:
SELECT ad_id, AVG(subscribed) as CR
FROM videoadcampaign
WHERE clicked = 'TRUE'
GROUP BY ad_id;
I have a table that stores monthly data and I would like to create a comparison between the quantity movement within a period.
Here is an example of the table
.
The SQL statement below is meant to return any changes that has happened within a period - any fund/policy partial or total loss as well as partial or total gain. I have been battling with it for a while - any help would be well appreciated.
I currently have 5 sets of unions - (where the policies and funds match and there's a difference in quantities held, where the policies exist in the previous and not in the current and vice versa and where the securities exist in the previous and not in the current and vice versa) but the other unions work save for the last couple (where the securities exist in the previous and not in the current and vice versa). It doesn't seem to return every occurrence.
SELECT distinct pc.[Client]
,pc.Policy
,cast(pc.Qty as decimal) AS CurrQ
,0 AS PrevQ
,cast(pc.Qty as decimal) - 0 AS QtyDiff
,CASE WHEN cast(pc.Qty as decimal) - 0 > 0 THEN 'Bought Units'
WHEN cast(pc.Qty as decimal) - 0 < 0 THEN 'Sold Units'
ELSE 'Unknown'
END AS TransactionType
,convert(varchar,cast(pc.[ValDate] as date),103) AS CurrValDate
,'' AS PrevValDate
FROM table pc
WHERE convert(varchar,cast(pc.[ValDate] as date),103) = convert(varchar,getdate(),103)
AND pc.Policy IN (SELECT policy
FROM table
WHERE convert(varchar(10),[ValDate],103) = convert(varchar(10),getdate()-1,103)
AND pc.[Fund] NOT IN (SELECT PM.[Fund]
FROM table pc
LEFT JOIN table pm ON pc.policy = pm.policy
WHERE convert(varchar,cast(pc.[ValDate] as date),103) = convert(varchar,getdate(),103))
AND convert(varchar,cast(pm.[ValDate] as date),103) = convert(varchar,getdate()-1,103))
As #Larnu rightly mentioned in the comment section, the extra conditions in the query changed the run from a LEFT JOIN to an INNER JOIN. I changed the code to have policy, fund and date in the ON clause:
FROM table pc
LEFT JOIN table pm ON (pc.policy = pm.policy
AND pc.fund = pm.fund
AND pc.[ValDate]-1 = pm.[ValDate])
and got rid of the sub queries.
Thanks again Larnu.
I have two CTEs using the same table which holds receipts. Receipt type "a" says how much is billed and may or may not have an amount received. Receipt type "b"s have how much was received if it was received outside of the original receipt. These are matched up by mnth, cusnbr and job. Also on the receipt is how much is allocated for different expenses on the receipt.
I am trying to total up peoples hours if the receipt has been paid at least 99%. These records are based on cusnbr, jobnbr and mnth also. The code below works fine.
with billed as(Select cusnbr
,job
,mnth
,sum(bill_item_1) as 'Billed Item'
,sum(billed) as 'Billed'
From accounting
Where mytype in ('a','b')
Group by cusnbr
,job
,mnth)
paid as(Select cusnbr
,job
,mnth
,sum(rcpt_item_1) as 'Rcpt Item'
,sum(billed) as 'Paid'
From accounting
Where mytype in ('a','b')
Group by cusnbr
,job
,mnth)
Select b.cusnbr
,b.job
,b.mnth
,sum(g.hours) as 'Total Hours'
,b.[Billed Item]
,p.[Rcpt Item]
From billed b inner join paid p
on b.cusnbr = p.cusnbr
and b.job = p.job
and b.mnth = p.mnth
inner join guys g
on b.cusnbr = g.cusnbr
and b.job = g.job
and b.mnth = g.mnth
Where p.[Paid]/b.Billed > .99
The issue I'm having is if I try to add
and b.[Billed Item] <> 0
To the where clause.
I get "Divide by zero error encountered"
I have tried making the last query a CTE with
case when b.[Billed Item] = 0 then 1 else 0 end as flag
and then making another query which checks that flag <> 0
I have tried using isnull(b.[Billed Item],0) in the last query as well as isnull(bill_item_1,0) in the first CTE.
I can get around this issue by dumping the whole thing into a temp table and querying that, but just want to know why this is happening. Using ">","<" or "<>" against b.[Billed Item] results in a divide by zero error.
Use nullif():
Where p.[Paid] / nullif(b.Billed, 0) > 0.99
This will return null -- which does not meet the condition. You can also phrase this more simply without division as:
where p.paid > b.billed * 0.99
I can't answer you question specifically, but I can tell you that SQL does not process all commands if it does not need to. For example,
SELECT COUNT(1/0)
Happily returns 1. So it is quite possible the order of the conditions cause the optimizer to filter out an uncessary division by zero condition.
I'm presently making a report on ssrs from a Great Plains Dynamics DB.
It's a pretty simple report with a few columns. Everything works fine but in GP, when creating an Invoice or a Return bill, sometimes GP is gonna give the same Bill ID. It doesn't really shows as a duplicated because for GP, an Invoice and a Return can/could have the same ID because they are not the same type. Don't ask me why..
So for my report, when I start a research from a multiples values parameters with my SopNumber (Bill ID) it gives me the right information. But now I would like to have a flag on those information that equals the bill ID and has Invoice and Return at the same time.
Since it is normal for GP to have 2 different type of document for the same ID, I cannot ask my report to remove the return or the invoice cause in different case, an Invoice could be the important document and in an other case, the return.
In my tablix, I do not show the Bill ID, because I don't need the information except when there is this "duplication".
I would also like after the flag (line highlited), that on the top of my report, a sentence shows something like : "Those documents are in conflict : 000123123". So with this information showing my ID, I can now go in my multiple values parameter and remove this number.
I wanna achieve those 2 flags because I'm making a calcul from my documents amount and if those 2 would be there, it would make my calcul wrong.
I hope you guys can help me. If so, thank you very much in advance!
I worked on a couple of different expressions but never got the result I wanted. Use previous statement and equals but couldn't find how to make it look like is equals to Invoice and Return and SopNumber equals the same.
select CASE SOP10200.SOPTYPE
WHEN 1 THEN 'QUOTE'
WHEN 2 THEN 'ORDER'
WHEN 3 THEN 'INVOICE'
WHEN 4 THEN 'RETURN'
WHEN 5 THEN 'BACK ORDER'
WHEN 6 THEN 'FULLFILLMENT ORDER'
END AS SOPTYPE,
sop10200.SLPRSNID,
sop10200.XTNDPRCE as ExtendedPrice,
sop10200.SOPNUMBE,
iv00101.ITMCLSCD as FAMILYCLASS,
sop10100.DOCDATE
from sop10200
left join iv00101 on sop10200.ITEMNMBR = iv00101.ITEMNMBR
left join sop10100 on sop10200.SOPNUMBE = sop10100.SOPNUMBE
WHERE SOP10100.DOCDATE BETWEEN '2018-01-01 00:00:00.000' AND '2035-01-01 00:00:00.000'
union all
select CASE SOP30300.SOPTYPE
WHEN 1 THEN 'QUOTE'
WHEN 2 THEN 'ORDER'
WHEN 3 THEN 'INVOICE'
WHEN 4 THEN 'RETURN'
WHEN 5 THEN 'BACK ORDER'
WHEN 5 THEN 'FULLFILLMENT ORDER'
END AS SOPTYPE,
sop30300.SLPRSNID,
sop30300.XTNDPRCE as ExtendedPrice,
sop30300.SOPNUMBE,
iv00101.ITMCLSCD as FAMILYCLASS,
sop30200.DOCDATE
from sop30300
left join iv00101 on sop30300.ITEMNMBR = iv00101.ITEMNMBR
left join sop30200 on sop30300.SOPNUMBE = sop30200.SOPNUMBE
WHERE SOP30200.DOCDATE BETWEEN '2018-01-01 00:00:00.000' AND '2035-01-01 00:00:00.000'
ORDER BY SOPNUMBE desc
Correct me if I'm wrong, but it sounds like you want a way to see if there is a duplicate record for the report and use that in a calculation?
You could do a subquery to retrieve a count, and if that is more than 1 than you have a duplicate record
EDIT:
SELECT *, (IF
(SELECT Count(S1.SOPTYPE) FROM sop10200 S1 WHERE T1.BillID = S1.BillID ) > 1 THEN "Duplicate " ELSE "" END) AS DuplicateCheck
FROM sop10200 T1
The above solution will give you a value you can use on each page to report whether or not that it has a duplicate BillID.