How to return null values if there is no data to display in BigQuery [duplicate] - google-bigquery

This question already has answers here:
Display default value if query results in no records in BigQuery
(2 answers)
Closed 10 months ago.
My question is I want to get null values when there is "no data to display" in the BigQuery.
like this:
But it only works when there are only aggregate functions. How to modify below query so that returns null values?
My query:
select oid, date, coalesce(sum(quantity_sold),0) as quantity_sold
from table
where oid = 'xxx' and (date >= 'xxx' and date <= 'xxx')
group by 1,2

I found this similar SO question but it creates a column that contains a message that says "Results not found" and assigns null values to other columns. You can apply this query and remove the message and retain only the null values, your query will look like this:
with sample_data as (
select 123 as oid, '2022-01-01' as date, 23 as quantity_sold
union all select 111 as oid, '2022-01-02' as date, 24 as quantity_sold
),
actual_query as (
select oid,date,coalesce(sum(quantity_sold),0) as quantity_sold
from sample_data
where oid = 534 and (date >= '2021-03-23' and date <= '2021-04-23')
group by 1,2
)
-- query below is the modified query from the linked SO question above
select actual_query.*
from actual_query
union all
select actual_query.* -- all the `actual_query` columns will be `NULL`
from (select 1) left join
actual_query
on 1 = 0 -- always false
where not exists (select 1 from actual_query);
Sample output:
NOTE: I created random values for sample data that could mimic the message "There is no data to display" when I ran your query.

Related

How to select the best item in each group?

I have table reports:
id
file_name
1
jan.xml
2
jan.csv
3
feb.csv
In human language: there are reports for each month. Each report could be in XML or CSV format. There could be 1-2 reports for each month in unique format.
I want to select the reports for all months, picking only 1 file for each month. The XML format is more preferable.
So, expected output is:
id
file_name
1
jan.xml
3
feb.csv
Explanation: the file jan.csv was excluded since there is more preferable report for that month: jan.xml.
As mentioned in the comments your data structure has a number of challenges. It really needs a column for ReportDate or something along those lines that is a date/datetime so you know which month the report belongs to. That would also give you something to sort by when you get your data back. Aside from those much needed improvements you can get the desired results from your sample data with something like this.
create table SomeFileTable
(
id int
, file_name varchar(10)
)
insert SomeFileTable
select 1, 'jan.xml' union all
select 2, 'jan.csv' union all
select 3, 'feb.csv'
select s.id
, s.file_name
from
(
select *
, FileName = parsename(file_name, 2)
, FileExtension = parsename(file_name, 1)
, RowNum = ROW_NUMBER() over(partition by parsename(file_name, 2) order by case parsename(file_name, 1) when 'xml' then 1 else 2 end)
from SomeFileTable
) s
where s.RowNum = 1
--ideally you would want to order the results but you don't have much of anything to work with in your data as a reliable sorting order since the dates are implied by the file name
You may want to use a window function that ranks your rows by partitioning on the month and ordering by the format name, by working on the file_name field.
WITH ranked_reports AS (
SELECT
id,
file_name,
ROW_NUMBER() OVER(
PARTITION BY LEFT(file_name, 3)
ORDER BY RIGHT(file_name, 3) DESC
) AS rank
FROM
reports
)
SELECT
id,
file_name
FROM
ranked_reports
WHERE
rank = 1

How to check another column value to be the highest to determine the latest record that occurs multiple times in Oracle SQL Developer? [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)
Select First Row of Every Group in sql [duplicate]
(2 answers)
Return row with the max value of one column per group [duplicate]
(3 answers)
Get value based on max of a different column grouped by another column [duplicate]
(1 answer)
SQL: getting the max value of one column and the corresponding other columns [duplicate]
(2 answers)
Closed 2 years ago.
I have a table called ro_main_table which stores details of productions such as serial_nr, pr_date_time, machine_nr, record_key etc. I would like to get the distinct machine_nr and record key from ro_main_table where pr_date_time is in last 6 hours. For this I do:
select machine_nr, record_key, pr_date_time from ro_main_table where pr_date_time >= SYSDATE - 6/24;
Which gives me the table below:
MACHINE_NR
RECORD_KEY
PR_DATE_TIME
54
9809
17-DEC-20 04.02.35.000000000 AM
55
9811
17-DEC-20 04.58.22.000000000 AM
55
9817
17-DEC-20 09.17.50.000000000 AM
54
9814
17-DEC-20 07.57.24.000000000 AM
50
9818
17-DEC-20 09.45.22.000000000 AM
However, as you see there might be machines which are started twice during this time (i.e. machine_nr occurs multiple times). If this is the case, I will choose the record which has the highest record_key. For example, for machine 55 it is 9817. How can I achieve this?
Thank you very much in advance!
select machine_nr, max(record_key), pr_date_time
from ro_main_table
where pr_date_time >= SYSDATE - 6/24
group by machine_nr;
this query should get the result you wish
I found a way. I create an inner join like this:
select tt.machine_nr, tt.record_key, tt.pr_date_time
from ro_main_table tt
INNER JOIN
(SELECT machine_nr, MAX(record_key) AS MaxRecordKey
FROM ro_main_table
GROUP BY machine_nr) groupedtt
ON tt.machine_nr = groupedtt.machine_nr
AND tt.record_key = groupedtt.MaxRecordKey
where pr_date_time >= SYSDATE - 6/24;
You can use the window function as follows:
select * from
(select machine_nr, record_key, pr_date_time
row_number() over (partition by machine_nr order by record_key desc) as rn
from ro_main_table where pr_date_time >= SYSDATE - 6/24)
where rn = 1;

Need suggestion with a for loop for postgres code

I need to write a postgres query to fetch cluster id's for a beta_plan_id and do some operation later.. for a single beta_plan_id in the below table there may be many merch id and so many cluster_id. how will this be handled??
BETA_PLAN_ID MERCH_LEVEL1_ID BETA_PLAN_MERCH_LVL1_CLSTR_ID NO_OF_STORES
1 1 12 5,6,7
1 1 13 9,10
1 1 14 2,3,4
2 2 15 13,12
SELECT BETA_PLAN_MERCH_LVL1_CLSTR_ID INTO i_clstr_id
FROM beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR
WHERE BETA_PLAN_ID = in_beta_plan_id;
the problem is many results will be returned since BETA_PLAN_MERCH_LVL1_CLSTR_ID is a serial type and uniquely generated for (beta_plan_id, merch_id,cluster_id) combo.
SELECT BETA_PLAN_MERCH_LVL1_CLSTR_ID
INTO i_clstr_id
FROM beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR
WHERE BETA_PLAN_ID = in_beta_plan_id;
INSERT INTO beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR
(
BETA_PLAN_ID,
MERCH_LEVEL1_ID,
CLUSTER_ID,
CLUSTER_NAME,
NO_OF_STORES,
NO_OF_FOOTAGE_VARIATION,
CREATED_USER,
CREATED_TS
)
SELECT
out_plan_id,
merch_lvl1_clstr.MERCH_LEVEL1_ID,
merch_lvl1_clstr.CLUSTER_ID,
merch_lvl1_clstr.CLUSTER_NAME,
merch_lvl1_clstr.NO_OF_STORES,
merch_lvl1_clstr.NO_OF_FOOTAGE_VARIATION
in_user_id,
now()
FROM beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR merch_lvl1_clstr
INNER JOIN beta_plan.BETA_PLAN_MERCH_COPY_PLAN merch_copy
ON merch_copy.MERCH_ID = merch_lvl1_clstr.MERCH_LEVEL1_ID
AND merch_lvl1_clstr.BETA_PLAN_ID = in_beta_plan_id
RETURNING BETA_PLAN_MERCH_LVL1_CLSTR_ID INTO o_clstr_id;
INSERT INTO beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR_STR
(
BETA_PLAN_MERCH_LVL1_CLSTR_ID,
STORE_ID,
CREATED_USER,
CREATED_TS
)
SELECT
o_clstr_id,
STORE_ID,
in_user_id,
now()
FROM beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR_STR
WHERE BETA_PLAN_MERCH_LVL1_CLSTR_ID = i_clstr_id;
Instead of the first SELECT statement, use a FOR loop that encloses the other statements:
FOR i_clstr_id IN
SELECT BETA_PLAN_MERCH_LVL1_CLSTR_ID
FROM beta_plan.BETA_PLAN_MERCH_LVL1_CLSTR
WHERE BETA_PLAN_ID = in_beta_plan_id
LOOP
/* your two INSERT statements come here */
END LOOP;
See the documentation for details.

Inserting multiple records based on select and check records exists + Sql [duplicate]

This question already has answers here:
SQL Server insert if not exists best practice [closed]
(8 answers)
Closed 7 years ago.
Hi I have created a sql query as seen below. Basically I need to achieve two things.
1. Insert record only if the correlationid doesnt exist in correlationmessage table.
2. Insert two records one with MessageTypeId = 1 and MessageTypeId = 2.
I have tried and achieved the second one but dont know how to do the first one
insert into MESSAGING.CorrelationMessage
(CorrelationId, MessageTypeId, RequestMessage,ResponseMessage, IsMatched, CreatedDate)
(
Select ActivityID, 1 as MessageTypeId, NULL as RequestMessage, NULL as ResponseMessage, 1 as IsMatched, GETDATE() as CreatedDate
from account.Activity a
join account.ActivityType b on b.ActivityTypeID=a.ActivityTypeID
join ACCOUNT.TransactionType c on c.TransactionTypeID=a.TransactionTypeID
where a.ActivityTypeID=3
and ExecutingBroker is null
and a.active=1
and TradeDate is null
and DateforGTDOrders > GETDATE()
union
Select ActivityID, 2 as MessageTypeId, NULL as RequestMessage, NULL as ResponseMessage, 1 as IsMatched, GETDATE() as CreatedDate
from account.Activity a
join account.ActivityType b on b.ActivityTypeID=a.ActivityTypeID
join ACCOUNT.TransactionType c on c.TransactionTypeID=a.TransactionTypeID
where a.ActivityTypeID=3
and ExecutingBroker is null
and a.active=1
and TradeDate is null
and DateforGTDOrders > GETDATE()
)
This query is a bit different as it to doing multiple inserts based on select as also checking if the record exists. Since it is a union it is quite tricky to do the check.
With in your insert, you can:
select * from
(Select ActivityID,1 as MessageTypeId,NULL as RequestMessage ,NULL as ResponseMessage,1 as IsMatched ,GETDATE() as CreatedDate from account.Activity a
join account.ActivityType b on b.ActivityTypeID=a.ActivityTypeID
join ACCOUNT.TransactionType c on c.TransactionTypeID=a.TransactionTypeID
where a.ActivityTypeID=3
and ExecutingBroker is null
and a.active=1
and TradeDate is null
and DateforGTDOrders > GETDATE()
union
Select ActivityID,2 as MessageTypeId,NULL as RequestMessage ,NULL as ResponseMessage,1 as IsMatched ,GETDATE() as CreatedDate from account.Activity a
join account.ActivityType b on b.ActivityTypeID=a.ActivityTypeID
join ACCOUNT.TransactionType c on c.TransactionTypeID=a.TransactionTypeID
where a.ActivityTypeID=3
and ExecutingBroker is null
and a.active=1
and TradeDate is null
and DateforGTDOrders > GETDATE()) ab
where not exits ( select 1 from MESSAGING.CorrelationMessage a where a.CorrelationId = ab.CorrelationId and ab.MessageTypeId = a.MessageTypeId)
I have not tried this query but please give it a shot, I know this would not be most optimized way to do it. But, you would need to tune it. This is just an idea.

SQL Column results with NULL Values

I am having the following issue with my query.
I am trying to import data from multiple tables (Fact_Contact, Quali_Seg, etc…) into one table (Fact_Forecast). This is to predict how many individuals are eligible for a specific offer. The problem I am having is that for some reason, the column Date_ID, which is been pulled from Fact_Contact, when importing has NULL values. I don’t know where these NULL values are coming from as the table Fact_Contact don’t have any NULL values in the column DATE_ID.
This is the section of the query that has the problem,
DECLARE #lastDateID int
SELECT TOP 1 #lastDateID = date_id
FROM Fact_Contact
ORDER BY CREATE_DATE DESC
SELECT date_id, Offers.Segmentation_id, Offers.Offer_Code, Offers.Wave_no,
Offers.cadencevalue,
CASE
WHEN dailydata.activity_count IS NOT NULL THEN dailydata.activity_count
ELSE 0
END as "activity_count"
FROM (
SELECT s.Segmentation_id, s.Offer_Code, s.Wave_no, o.cadencevalue,
o.campaign_id, o.offer_desc
FROM Forecast_Model.dbo.Quali_Segment s
LEFT JOIN Forecast_Model.dbo.Dim_Offers o
ON s.offer_code = o.offer_code
) Offers
LEFT JOIN (
SELECT date_id, Offer_Code_1 Offer_Code,
segmentation_group_id, Count(indv_role_id) Activity_count
FROM Forecast_Model.dbo.Fact_Contact
WHERE date_id = #lastDateID
GROUP BY offer_code_1,segmentation_group_id,date_id
) DailyData
ON DailyData.offer_code = Offers.offer_code
AND Offers.Segmentation_id = dailydata.segmentation_group_id
ORDER BY Segmentation_id,Wave_no
The column Date_ID as I mentiones gets only 2 dates which is the same as the #LastDateID which is 2014-05-20 but the rest are NULL.
Thank you,
Omar
date_id will be NULL whenever you have records in Offers (join Quali_Segment) but no matching records in Fact_Contact