I'm just learning Qlikview and am struggling with the syntax for set analysis. I have a dimension called OPEN_DT which is a date field. For this little exercise I just want to have the expression count the records where the date is on or before 02/27/2014. Step 2 will be to make the date dynamic but for now I'm at the "Hello, World" stage.
I've tried the following and what feels like 50 variations thereof...
COUNT({
<
OPEN_DT = {"<{(= Date('2014-02-27', 'yyyy-MM-dd'))} "}
>} MTTER_ID)
Can anyone help me sort this out?
This should work:
COUNT({
<
OPEN_DT = {"$(=Date(Date#('2014-02-27', 'YYYY-MM-DD')))"}
>} MTTER_ID)
or with a variable (using calendar object):
COUNT({
<
OPEN_DT = {"$(=Date(vTheDate))"}
>} MTTER_ID)
Related
I trying to write the following SQL code in DAX.
select SUM(amount) from TABLE
where BusinessDate = '2023-02-11'
OR (Segment = 'General' and Days_Without_Payments < 210)
OR (Segment = 'Enterprise' and Days_Without_Payments < 1215)
OR (Segment = 'House' and Days_Without_Payments < 1945)
I got the first part(i-e. SUM) right, but can't get my head around the filters.
What I tried:
Measure = CALCULATE([Total Outstanding],
FILTER(VALUES(BILBL_WO[Date]),BILBL_WO[Date]=MAX(BILBL_WO[Date])),
AND(BILBL_WO[Days_Without_Payments] < 210, BILBL_WO[Segment] = "General") ||
AND(BILBL_WO[Days_Without_Payments] < 1215, BILBL_WO[Segment] = "Enterprise") ||
AND(BILBL_WO[Days_Without_Payments] < 1945, BILBL_WO[Segment] = "House")
)
Where Total Outstanding is another Measure which I created for summation of Amount.
Please help as I couldn't find something useful from internet and I am new at this. Thanks!
In general, when people start learning DAX, most think it is like SQL query, but that is not true because SQL is a structured query language. In contrast, DAX is a formula language used for analysis purposes similar to excel equations.
I will give you a few pointers on how to convert SQL to DAX in simple terms considering you have one table that you imported to Power BI or SSAS tabular model, which are as follow:
You need to segregate your query as follows:
Aggregation function in your example SUM (amount) in SQL query will be in DAX:
Total Outstanding = sum('BILBL_WO'[amount])
Where condition on a date column:
I usually create a date dimension and create a relation with the table that has the date column. You can do that when you go into more details relating to evaluation context in Power BI and Star schema architecture as a start, but in your case, if the column data type is a string, convert it to date type and then use the date column as a filter in the power bi report page, allowing the report users to select different dates, not just ‘2023-02-11'.
For your conditions on Segment and Days_Without_Payments, before converting it to DAX, I think your original query is missing Parenthesis. If I understand it correctly, please let me know if I am wrong.
select SUM(amount)
from TABLE
where BusinessDate = '2023-02-11'
and
(
(Segment = 'General' and Days_Without_Payments < 210)
OR
(Segment = 'Enterprise' and Days_Without_Payments < 1215)
OR
(Segment = 'House' and Days_Without_Payments < 1945)
)
Altered SQL script
If my above assumption is valid and you need to write a DAX measure with the Segment and Days_Without_Payments conditions, you can write it as follow:
Measure = CALCULATE([Total Outstanding] ,
KEEPFILTERS(
FILTER(
ALL(BILBL_WO[Segment] ,BILBL_WO[Days_Without_Payments]),
(BILBL_WO[Segment] = "General" && BILBL_WO[Days_Without_Payments] < 210)
||
(BILBL_WO[Segment] = "Enterprise" && BILBL_WO[Days_Without_Payments] < 1215)
||
(BILBL_WO[Segment] = "House" && BILBL_WO[Days_Without_Payments] < 1945))
)
)
And for more on how to filter DAX using multicolumn, see this YouTube video https://www.youtube.com/watch?v=kQjYG6TJVp8 and follow the SQLBI channel. It will help you a lot.
I hope I helped in a way; if so, please mark this as an answer and vote for it :)
I'm trying to query a database(not owned by me) that contains the following columns :
NumEpoca (epoch), Turma(class), Dia (day - indicates day of the week),
Hora (hour - each value indicates a 30mins time, a 3h class generate 6 tuples),
Disciplina (course), TipoAula (type of class, theoretical or practical),
Sala (classroom)
This is basically a class schedule, so for a given Class, in the same day of the week I can have in one week a practical class and in the other a theoretical class.
Now, I want to get for a given day, the minimum and max hour (so I can calculate the starting and ending hour of the class), but I also want to get the classrooms for them, and I don't know at priori, if it's going to be a theoretical or practical class.
Also, certain classes are only practical, and some are only theoretical, so I just want 1 classroom.
The query I'm doing, gives me basically everything but
LectureDetails(beginDate=2020-05-26 15:30:00, endDate=2020-05-26 18:30:00, classroom=L_H1/G.0.08)
LectureDetails(beginDate=2020-05-26 15:30:00, endDate=2020-05-26 18:30:00, classroom=G.0.08/L_H1)
as you can see here, I get the same class (that starts and ends at the same hour, for the 2 classrooms Teo and Pract. But I only need 1 tuple for that day and I'm getting L_H1/G.0.08 and G.0.08/L_H1.
"SELECT a1.Dia,MIN(a1.Hora),MAX(a1.Hora),a1.Sala, a2.Sala FROM Aulas as a1 LEFT JOIN Aulas as a2 " +
"on a1.Sala <> a2.Sala and a1.Disciplina = a2.Disciplina and a1.NumEpoca = a2.NumEpoca and a1.Turma = a2.Turma " +
"and a1.Dia= a2.Dia and a1.Hora = a2.Hora " +
"where NumEpoca = ? AND Turma = ? AND Disciplina=? GROUP BY a1.Dia,a1.Sala,a2.Sala"
Thanks in advance.
You could have eliminated the mis-ordered results by using a1.Sala < a2.Sala instead of the inequality.
But that's not really the approach you want anyway. Try something like this:
SELECT Dia, MIN(Hora), MAX(Hora),
MIN(Sala),
CASE WHEN MIN(Sala) = MAX(Sala) THEN NULL ELSE MAX(Sala) END
FROM Aulas
WHERE NumEpoca = ? AND Turma = ? AND Disciplina = ?
GROUP BY Dia
I was working on the conversion of a sql request into a dax one :
>;WITH cte
>AS
>(
> SELECT uc.idU_Email
> ,uc.id_Type
> ,uc.dRecueil
> ,valeur
> ,ROW_NUMBER() OVER(PARTITION BY idU_Email,id_Type ORDER BY dRecueil DESC, valeur ASC) AS rang
> FROM vUE uc
> WHERE uc.Id_Type=1 AND uc.dRecueil<=(DATEADD(month, -1, GETDATE()))
>)
>SELECT COUNT(idU_Email)
> FROM cte
> WHERE rang = 1
> and valeur = 1
If i understood well, the equivalent of the rownumber function in sql in the RANKX Function in DAX.
So basically, to achieve the conversion i created a new calculated colum with the following expression :
Ranking on partition
To resume it, it makes a ranking on every parition of idU_Email order by dRecueil and then by valeur.
Thus, the only thing left to do was to add a condition on the date (like in my SQL request), but i guess i don't really know how (or where?), and an error occurred when i tried, which i haven't achieved to solved yet :
Ranking on partition with filter on date
I hope someone would find a way to solve that issue (or even to propose me a better way to have the equivalent of my SQL request).
Thanks by advance ! Smiley Happy
[UPDATE]
I've achieved to partition as I wanted to do and to apply a date filter like that :
RANK_OnDate = IF(vUE[dRecueil] <= DATE(YEAR(TODAY()); MONTH(TODAY())-1; DAY(TODAY()))
;RANKX(FILTER(vUE; vUE[idU_Email] = EARLIER(vUE[idU_Email]) && vUE[id_Type] = EARLIER(vUE[id_Type]))
;RANKX(ALL(vUE); vUE[dRecueil]; ;ASC)
+
DIVIDE(
RANKX(ALL(vUE); vUE[valeur]; ; DESC; Skip)
;COUNTROWS(ALL(vUE)) + 1
)
)
)
But, actually, i would like it to filter dynamically... Thus i don't know if it would be better to use that directly in a measure (according that i want to count distinctly the lower/higher rank for each idU_email).
Additionally my filter just apply blank when the date isn't ok with the filter but the ranking stay the same...
I tried to do directly the distinct count in a measure but can't save the different issues encountered... Have you got some ideas ?
(and thanks for your answers) :)
I think you're pretty close, try this
Rank = IF(vUE[dRecueil] <= DATE(YEAR(TODAY()), MONTH(TODAY())-1, DAY(TODAY())),
RANKX(FILTER(vUE, vUE[idU_Email] = EARLIER(vUE[idU_Email])),
RANKX(ALL(vUE), vUE[dRecueil], ,ASC) +
DIVIDE(
RANKX(ALL(vUE), vUE[valeur], , DESC, Skip),
COUNTROWS(ALL(vUE)) + 1)))
I'm trying to avoid using straight up SQL in my Rails app, but need to do a quite large version of this:
SELECT ds.product_id,
( SELECT SUM(units) FROM daily_sales WHERE (date BETWEEN '2015-01-01' AND '2015-01-08') AND service_type = 1 ) as wk1,
( SELECT SUM(units) FROM daily_sales WHERE (date BETWEEN '2015-01-09' AND '2015-01-16') AND service_type = 1 ) as wk2
FROM daily_sales as ds group by ds.product_id
I'm sure it can be done, but i'm struggling to write this as an active record statement. Can anyone help?
If you must do this in a single query, you'll need to write some SQL for the CASE statements. The following is what you need:
ranges = [ # ordered array of all your date-ranges
Date.new(2015, 1, 1)..Date.new(2015, 1, 8),
Date.new(2015, 1, 9)..Date.new(2015, 1, 16)
]
overall_range = (ranges.first.min)..(ranges.last.max)
grouping_sub_str = \
ranges.map.with_index do |range, i|
"WHEN (date BETWEEN '#{range.min}' AND '#{range.max}') THEN 'week#{i}'"
end.join(' ')
grouping_condition = "CASE #{grouping_sub_str} END"
grouping_columns = ['product_id', grouping_condition]
DailySale.where(date: overall_range).group(grouping_columns).sum(:units)
That will produce a hash with array keys and numeric values. A key will be of the form [product_id, 'week1'] and the value will be the corresponding sum of units for that week.
Simplify your SQL to the following and try converting it..
SELECT ds.product_id,
, SUM(CASE WHEN date BETWEEN '2015-01-01' AND '2015-01-08' AND service_type = 1
THEN units
END) WK1
, SUM(CASE WHEN date BETWEEN '2015-01-09' AND '2015-01-16' AND service_type = 1
THEN units
END) WK2
FROM daily_sales as ds
group by ds.product_id
Every rail developer sooner or later hits his/her head against the walls of Active Record query interface just to find the solution in Arel.
Arel gives you the flexibility that you need in creating your query without using loops, etc. I am not going to give runnable code rather some hints how to do it yourself:
We are going to use arel_tables to create our query. For a model called for example Product, getting the Arel table is as easy as products = Product.arel_table
Getting sum of a column is like daily_sales.project(daily_sales[:units].count).where(daily_sales[:date].gt(BEGIN_DATE).where(daily_sales[:date].lt(END_DATE). You can chain as many wheres as you want and it will be translated into SQL ANDs.
Since we need to have multiple sums in our end result you need to make use of Common Table Expressions(CTE). Take a look at docs and this answer for more info on this.
You can use those CTEs from step 3 in combination with group and you are done!
I'm having a little problem to convert this SQL query to JPQL:
select max(datePurchase) from purchases where userId = id and date_trunc('day',datePurchase)
in (select distinct (date_trunc('day',datePurchase)) as day from purchases where userId = id and datePurchase < initialDate and datePurchase > finalDate) group by date_trunc('day',datePurchase)
This sql is working well, that returns de last purchase per day made from a user. I tried to do the same, in JPQL:
Query query = em.createQuery("SELECT u MAX(u.datePurchase) FROM Purchases u WHERE u.userId.id = :id AND FUNC('day',u.datePurchase)" +
"IN (SELECT DISTINCT (FUNC('day',u.datePurchase)) AS day FROM Purchases WHERE u.userId.id = :id AND u.datePurchase < :finalDate AND u.datePurchase > :inicialDate) GROUP BY FUNC('day',u.datePurchase)");
query.setParameter("id", idUsuario);
query.setParameter("dataInicial", dataInicial);
query.setParameter("dataFinal", dataFinal);
List<MovSaldo> saldos = (List<MovSaldo>) query.getResultList();
em.getTransaction().commit();
The errors are:
"The IN expression does not have a valid expression." "An identification variable must be provided for a range variable declaration."
Probably is not something very difficult, but i have already spent a little frustrating time in it. Can someone please help me?
Although the answer is probably late for you I still posted it because it might help someone in the future.
In the nested select you have to put an identifier for the entity you are working with: FROM Purchases p and update things like (FUNC('day',u.datePurchase)) to (FUNC('day',p.datePurchase))
Best!