If statement when a parameter in the macro is null in dbt - if-statement

I am new using DBT so maybe you guys can help me create this macro. I have a macro as the one you can see below:
{% macro finding_number(missing_arn, acquirer_id, min_date, max_date) %}
{% set query %}
select
*
from {{ ref('hola') }}
where event_date::date between '{{min_date}}' and '{{max_date}}'
and acquirer_id = {{acquirer_id}}
and acquirer_reference_number = '{{missing_arn}}'
{% endset %}
{% set results = run_query(query) %}
{%endmacro%}
What is the problem here? That there might be some cases where I don't have an acquirer_id or a date to populate in the parameters of the macro. Find an example below:
dbt run-operation finding_number --args '{missing_arn: xyz}'
So, if I don't have a value for these parameters and I try to run the macro, it gives me an error as I haven't assigned any values to these parameters ( acquirer_id, min_date and max_date ).
I've seen this could be solve by using multiple If statements to "jump" through those conditions in the where statement inside the query if you haven't assigned anything to those parameters, but I don't know how to structure them. For this case, as we only have missing_arn, the if statement would need to "jump" over the condition of acquirer_id, min_date and max_date in the where statement, as we didn't assign any values to these two parameters in order to be able to run the macro.
Thanks!

How I would structure it to solve this quickly…
{% macro finding_number(missing_arn, acquirer_id, min_date, max_date) %}
{% set query %}
select
*
from {{ ref('hola') }}
where acquirer_reference_number = '{{missing_arn}}'
{{%- if min_date is not none and max_date is not none -%}} and event_date::date between '{{min_date}}' and '{{max_date}}' {%- endif -%}
{{%- if acquirer_id is not none -%}} and acquirer_id = {{acquirer_id}} {%- endif -%}
{% endset %}
{% set results = run_query(query) %}
{%endmacro%}
I did not include an if statement for the missing_arn because you asked about a scenario in which you did have that, HOWEVER, you could apply the same logical pattern as such…
where 1=1
{{%- if missing_arn is not none -%}} and acquirer_reference_number = '{{missing_arn}}' {{%- endif -%}}
The where 1=1 allows it to still run if all three are missing or different combination of parameters are left out.
Havent tested this, but give it a try.
Optional in case you have a min date but no max date or vice versa:
{{%- if min_date is not none -% }} and event_date::date >= '{{min_date}}' {%- endif -%}
{{%- if max_date is not none -% }} and event_date::date <= '{{max_date}}' {%- endif -%}

Related

Get order code from order entry in flexible search

I'm trying to get the order code from an OrderEntry. For now I have this query, that brings me the PK from Order but I need the ordercode.
SELECT * from (
{{
SELECT {o.order} FROM {OrderEntry as o} WHERE {o.message} is Null
}}
)

How to have HTML tags inside a jinja expression?

I have a variable test and it's value is Asia is the largest continent in the world
and in variable cname has value as Asia ,
Here I am trying to Bold the value Asia as below :
{{ test.replace(cname,<strong>cname</strong>) }}
But this gives me an error as, jinja2.exceptions.TemplateSyntaxError: unexpected '<'
required Output : Asia is the largest continent in the world
Is there a possible way to achieve this , any guiding links are much helpful , TIA
Use str.format() and use |safe filter to mark the string as safe. Without the |safe filter, HTML tags will be escaped, and appear "as is" on the rendered page.
{{ test.replace(cname,"<strong>{}</strong>".format(cname)) | safe }}

EmberJS - {{moment-format 'date' 'output' 'input'}} repeats todays date in every row when used in {{#each} block

I am using ember-moment addon in order to format the dates in the following table:
<tbody>
{{#each model as |model|}}
<tr class="clickable-row">
<td>{{model.id}}</td>
<td>{{model.first_name}}</td>
<td>{{model.last_name}}</td>
<td>{{model.date_of_birth}}</td>
<td>{{model.inserted_at}}</td>
<td>{{model.departed_at}}</td>
</tr>
{{/each}}
</tbody>
date_of_birth property returned from the DB ha the following format:
yyyy-mm-ddThh:mm:ss+|-hhmm
When I try to format it like below;
{{moment-format 'model.date_of_birth' 'DD/MM/YYYY' 'yyyy-mm-ddThh:mm:ss+|-hhmm' }}
I end up with a populated table full of unique rows, except the date of birth is just today's date on every single row.
I know I am missing something obvious and someone out there is going to make me look very silly!
You should pass binding date object to the helper instead of passing its name as a string. Therefore use it like this:
{{moment-format model.date_of_birth 'DD/MM/YYYY' }}

Django Monthly Grid / Table

I have a stock portfolio with monthly returns. Currently the returns are stored in the database as the first of each month, and the year.
So January 1, 2016 - 5%
February 1, 2016 - 3%
What's the best way to display this in a Django template?
I want to have each year in a separate row, and columns being the dates so:
Jan Feb Mar Apr....
2014
2015
2016
What's the best way to put the monthly returns into their correct position?
Thanks for the help!
I don't know if it is the best way, but I end up using a list of tuples for doing this.
In the views.py, make a dictionary entry that contains the line you want to display in a tuple and make a list of those lines:
def testview(request):
x = [(2014,1,2,3),(2015,4,5,6),(2016,7,8,9)]
return render(request, 'yourtemplate.html', {'data':x})
Next make a js table in your template (yourtemplate.html) and loop over the lines
<table>
<tr>
<th></th>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
</tr>
{% for tuple in data %}
<tr>
<th>{{tuple.0}}</th>
<th>{{tuple.1}}</th>
<th>{{tuple.2}}</th>
<th>{{tuple.3}}</th>
</tr>
{% endfor %}
</table>
I hope this helps!

Creating an Alphabetical Indexed List (ColdFusion + Microsoft SQL Server)

I'm currently struggling to find anyone who knows how this can be done? I've tried a few different methods and ended up with halfway results but not quite what i wanted. Basically i'm trying to create a list showing all the bands A-Z, but the band names are being called from a database, so i'm having to use #band_name# within a nested list. If i re-write the code and post it, someone might be able to see where i'm going wrong.
<cfoutput query="bandNameList">
<cfloop from="65" to="90" index="i">
<UL>
<LI> #chr(i)#
<UL>
<LI> #band_name# </LI>
</UL>
</LI>
</UL>
</cfloop>
</cfoutput>
What I think you're after is to only output the Letter for the first band that begins with that letter.
One way to achieve this is to change your query slightly (note I'm using what I think is SQL-92 syntax here, but there's probably a nicer way to get the first letter in your particular database):
select
band_name,
SUBSTRING(band_name from 1 for 1) AS first_letter
from
bands
order by
band_name
Which will get you the first letter in the query.
If you want to group all the bands with numeric first letters together, then you can use SQL's CASE statement to do that (you may need to find the equivalent to ascii() in your DBMS). You could also invert the logic and match against 'normal' letters and lump everything else into a '0-9 and punctuation' category if that's easier. I think that's what a number of music systems do (I'm thinking iTunes on the iPhone, but I'm sure there are others)
select
band_name,
CASE
WHEN ascii(left(band_name, 1)) BETWEEN 48 AND 57 THEN '0-9'
ELSE left(band_name, 1)
END AS first_letter
from
bands
order by
band_name
Now you can use that extra column along with cfoutput's group attribute to help get the output as you want it.
<UL>
<cfoutput query="bandNameList" group="first_letter">
<LI> #first_letter#
<UL>
<cfoutput>
<LI> #band_name# </LI>
</cfoutput>
</UL>
</LI>
</cfoutput>
</UL>
Update your query to have a left(band_name,1) AS BandStart and make sure to order by band_name in your ORDER BY. Then use group to output the list.
<cfoutput query="bandNameList" group="BandStart">
<UL>
<LI>#bandNameList.BandStart#
<cfoutput>
<UL>
<LI> #bandNameList.band_name# </LI>
</UL>
</cfoutput>
</LI>
</UL>
</cfoutput>
If you want to display all letters, even if no bands starting with that letter exist, another option is using a CTE to generate a table of letters A-Z. Then display the results with a "grouped" cfoutput:
<cfquery name="getBandNameList" ...>
;WITH ltrs ( code ) AS (
SELECT ascii('A') AS code
UNION ALL
SELECT code + 1
FROM ltrs
WHERE ascii('Z') > code
)
SELECT char(code) AS letter, t.band_name
FROM ltrs LEFT JOIN #YourTable t ON t.band_name LIKE char(code) +'%'
ORDER BY letter ASC, t.band_name ASC
</cfquery>
<cfoutput query="bandNameList" group="Letter">
<UL>
<LI> #letter#
<UL>
<cfoutput>
<LI> #band_name# </LI>
</cfoutput>
</UL>
</LI>
</UL>
</cfoutput>
Another approach is to write a sql server stored proc that returns everything in a single query object. The code would resemble this:
declare #thisNum as int
declare #lastNum as int
set #thisNum = 65;
set #lastNum = 90;
declare #letters as table(letter char(1))
while (#thisNum <= #lastNum)
begin
insert into #letters values (CHAR(#thisNum))
set #thisNum = #thisNum + 1;
end
select letter, bandname
from #letters left join band on letter = left(bandname, 1)
order by letter, bandname
Then, in ColdFusion, you can use cfoutput with the group attribute.
Try this code ::
<cfquery datasource="orcl" name="list">
select upper(brand) brand from tbl
</cfquery>
<cfoutput query="list">
<cfloop from="65" to="90" index="i">
<UL>
<LI> #chr(i)#
<UL>
<LI><cfif mid(brand,1,1) eq chr(i)> #brand#</cfif></LI>
</UL>
</LI>
</UL>
</cfloop>
</cfoutput>