Implementing where condition in DAX - sql

I have a scenario wherein I want to implement a BELOW SQL Query in Dax:
select count(distinct a.ID)
from Table1 a
join Table2 b
on a.ID=b.ID
where a.[In_Time] = "No" OR b.[In Time] = "No"
how do I implement using Dax?

You did not provide much of details as to what is is the relationship between t1 and t2 and whether you expect this through a DAX query or DAX measure.
Assuming you want this to be returned through DAX query with no relationship between t1 and t2 an equivalent DAX query would be following. It joins a filtered t1 and filtered t2 on desired criteria.
t1
| id | inTime |
|----|--------|
| 1 | yes |
| 1 | no |
| 2 | no |
| 3 | no |
| 4 | no |
| 5 | no |
| 6 | no |
t2
| id | inTime |
|----|--------|
| 1 | yes |
| 1 | no |
| 2 | yes |
| 3 | no |
| 5 | no |
Query
Table =
VAR _1 =
DISTINCT (
NATURALINNERJOIN (
SELECTCOLUMNS (
FILTER ( t1, t1[inTime] = "no" ),
"id", t1[id] + 0,
"inTIme", t1[inTime] & ""
),
SELECTCOLUMNS (
FILTER ( t2, t2[inTim] = "no" ),
"id", t2[id] + 0,
"inTIme", t2[inTim] & ""
)
)
)
VAR _2 =
ROW ( "count", COUNTX ( _1, [id] ) )
RETURN
_2
returns the following for VAR _1
| id | inTime |
|----|--------|
| 1 | no |
| 3 | no |
| 5 | no |

Related

Take the row after the specific row

I have the table, where I need to take the next row after the row which has course 'TA' and flag = 1. For this I created the column rnum (OVER DATE) which may help for finding it
| student | date | course | flag | rnum |
| ------- | ----- | ----------- | ---- | ---- |
| 1 | 17:00 | Math | null | 1 |
| 1 | 17:10 | Python | null | 2 |
| 1 | 17:15 | TA | 1 | 3 |
| 1 | 17:20 | English | null | 4 |
| 1 | 17:35 | Geography | null | 5 |
| 2 | 16:10 | English | null | 1 |
| 2 | 16:20 | TA | 1 | 2 |
| 2 | 16:30 | SQL | null | 3 |
| 2 | 16:40 | Python | null | 4 |
| 3 | 19:05 | English | null | 1 |
| 3 | 19:20 | Literachure | null | 2 |
| 3 | 19:30 | TA | null | 3 |
| 3 | 19:40 | Python | null | 4 |
| 3 | 19:50 | Python | null | 5 |
As a result I should have:
| student | date | course | flag | rnum |
| ------- | ----- | ------- | ---- | ---- |
| 1 | 17:20 | English | null | 4 |
| 2 | 16:30 | SQL | null | 3 |
There are many ways to get your desired result, let's see some of them.
1) EXISTS
You can use the EXISTS clause, specifying a subquery to match for the condition.
SELECT T2.*
FROM #MyTable T2
WHERE EXISTS (
SELECT 'x' x
FROM #MyTable T1
WHERE T1.course = 'TA' AND T1.flag = 1
AND T1.student = T2.student AND T2.rnum = T1.rnum + 1
)
2) LAG
You ca use window function LAG to access previous row for a given order and then filter your resultset with your conditions.
SELECT w.student, w.date, w.course, w.flag, w.rnum
FROM (
SELECT T1.*
, LAG(course, 1) OVER (PARTITION BY student ORDER BY rnum) prevCourse
, LAG(flag, 1) OVER (PARTITION BY student ORDER BY rnum) prevFlag
FROM #MyTable T1
) w
WHERE prevCourse = 'TA' AND prevFlag = 1
3) JOIN
You can self-JOIN your table on the next rnum and keep only the rows who match the right condition.
SELECT T2.*
FROM MyTable T1
JOIN MyTable T2 ON T1.student = T2.student AND T2.rnum = T1.rnum + 1
WHERE T1.course = 'TA' AND T1.flag = 1
4) CROSS APPLY
You can use CROSS APPLY to specify a subquery with the matching condition. It is pretty similar to EXISTS clause, but you will also get in your resultset the columns from the subquery.
SELECT T2.*
FROM #MyTable T2
CROSS APPLY (
SELECT 'x' x
FROM #MyTable T1
WHERE T1.course = 'TA' AND T1.flag = 1
AND T1.student = T2.student AND T2.rnum = T1.rnum + 1
) x
5) CTE
You can use common table expression (CTE) to extract matching rows and then use it to filter your table with a JOIN.
;WITH
T1 AS (
SELECT student, rnum
FROM #MyTable T1
WHERE T1.course = 'TA' AND T1.flag = 1
)
SELECT T2.*
FROM #MyTable T2
JOIN T1 ON T1.student = T2.student AND T2.rnum = T1.rnum + 1
Adding the rownumber was a good start, you can use it to join the table with itself:
WITH matches AS (
SELECT
student,
rnum
FROM table
WHERE flag = 1
AND course = 'TA'
)
SELECT t.*
FROM table t
JOIN matches m
on t.student = m.student
and t.rnum = m.rnum + 1

How can I subtract two row's values within same column using sql query in access?

(query access)
This is the table structure:
+-----+--------+--------+
| id | name | sub1 |
+-----+--------+--------+
| 1 | ABC | 6.27% |
| 2 | ABC | 7.47% |
| 3 | PQR | 3.39% |
| 4 | PQR | 2.21% |
+-----+--------+--------+
I want to subtract Sub1
Output should be:
+-----+--------+---------+------------------------------------+
| id | name | sub1 | |
+-----+--------+---------+------------------------------------+
| 1 | ABC | 6.27% | 0 First Rec no need Subtract |
| 2 | ABC | 7.47% | 1.2% <=(7.47-6.27) |
| 3 | PQR | 3.39% | 0 First Rec no need Subtract |
| 4 | PQR | 2.21% | -1.18% <=(2.21-3.39) |
+-----+--------+---------+------------------------------------+
Thank you so much.
If you can guarantee consecutive id values, then the following presents an alternative:
select t.*, nz(t.sub1-u.sub1,0) as sub2
from YourTable t left join YourTable u on t.name = u.name and t.id = u.id+1
Change YourTable to the name of your table.
This is painful, but you can do:
select t.*,
(select top 1 t2.sub1
from t as t2
where t2.name = t.name and t2.id < t.id
order by t2.id desc
) as prev_sub1
from t;
This gives the previous value or NULL for the first row. You can just use - for the subtraction.
An index on (name, id) would help a bit with performance. However, if you can upgrade to a better database, you can then just use lag().

Divide Sequential Records

I have a table in MS Access like:
table
+-----+-----+-----+
| 1st | 2nd | 3rd |
+-----+-----+-----+
| A | 1 | 100 |
| A | 2 | 200 |
| A | 3 | 300 |
| B | 1 | 100 |
| B | 2 | 200 |
| B | 3 | 300 |
| C | 1 | 100 |
| C | 2 | 200 |
| C | 3 | 300 |
+-----+-----+-----+
Now I want to read the values from the 3rd column, do some sort of manipulation to it and store them in to another table like:
summary
+-----+---------+---------+
| 1st | 2nd | 3rd |
+-----+---------+---------+
| A | 100/200 | 200/300 |
| B | 100/200 | 200/300 |
| C | 100/200 | 200/300 |
+-----+---------+---------+
In another words, for summary.2nd this means:
select table.3rd FROM table where table.1st = A AND table.2nd = 1
divided by
select table.3rd FROM table where table.1st = A AND table.2nd = 3
Can someone give me a hint how this could be done?
Maybe VBA / ADO Recordset etc?
One method is conditional aggregation:
select [1st],
max(iif([2nd] = 1, [3rd], null)) / max(iif([2nd] = 2, [3rd], null)) as [2nd],
max(iif([2nd] = 2, [3rd], null)) / max(iif([2nd] = 3, [3rd], null)) as [3rd]
from t
group by [1st];
Try this SQL
INSERT INTO Summary
SELECT DISTINCT a.[1st],
a.[3rd] / b.[3rd] AS [2nd],
a.[3rd] / c.[3rd] AS [3rd]
FROM ((tbl AS a
INNER JOIN tbl AS b
ON a.[1st] = b.[1st])
INNER JOIN tbl AS c
ON a.[1st] = c.[1st] )
WHERE a.[2nd] = 1
AND b.[2nd] = 2
AND c.[2nd] = 3
Here's another alternative, using calculated join criteria:
select
t1.[1st],
t1.[3rd]/t2.[3rd] as [2nd],
t2.[3rd]/t3.[3rd] as [3rd]
from
(
[table] t1 inner join [table] t2
on t1.[1st] = t2.[1st] and t1.[2nd] = t2.[2nd]-1
)
inner join [table] t3
on t1.[1st] = t3.[1st] and t1.[2nd] = t3.[2nd]-2
Since the 2nd column values 1, 2 & 3 are not hard-coded, this is applicable to any three integers in the 2nd column whose values differ sequentially by one.
Change [table] to the name of your table.

SQL : Comparing multiple values in one table with a single value in another Table

I have two tables Table 1 and Table 2
Table 1:
-------------------------------
| Ser | StartDate | Activity |
-------------------------------
| 1 | 2002-10-13 | 1 |
| 1 | 2002-10-13 | 2 |
| 1 | 2007-09-04 | 3 |
Table 2:
------------------------
|Ser|DateOfRegistration|
------------------------
| 1 | 2002-10-12 |
| 1 | 2007-09-02 |
Now, the result that I want is such that for Activity 1 and 2 the Date of registration should be before the Start Date and difference between the dates must be the least. Similarly, for Activity 3, the date of registration for Activity 3 should be before the start date. The result should look like this.
Table 3:
--------------------------------------------
|Ser|StartDate |DateofRegistration|Activity|
--------------------------------------------
| 1 |2002-10-13| 2002-10-12 | 1 |
| 1 |2002-10-13| 2002-10-12 | 2 |
| 1 |2002-09-04| 2002-09-02 | 3 |
How can I join Table 1 and 2 to get Table 3?
You can use outer apply:
select t1.*, t2.dateofregistration
from table1 t1 outer apply
(select top (1) t2.*
from table2 t2
where t2.ser = t1.ser and t2.dateofregistration < t1.startdate
order by t2.dateofregistration desc
) t2

Getting the last updated name

I am having a table having records like this:
+------+------+
| ID | name |
+------+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | A |
| 5 | B |
| 6 | A |
| 7 | A |
| 8 | A |
+------+------+
I need to get value of A after it was last updated from a different value, for example here it would be the row at ID 6.
Try this query (MySQL syntax):
select min(ID)
from records
where name = 'A'
and ID >=
(
select max(ID)
from records
where name <> 'A'
);
Illustration:
select * from records;
+------+------+
| ID | name |
+------+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | A |
| 5 | B |
| 6 | A |
| 7 | A |
| 8 | A |
+------+------+
-- run query:
+---------+
| min(ID) |
+---------+
| 6 |
+---------+
Using the Lag function...
SELECT Max([ID])
FROM (SELECT [name], [ID],
Lag([name]) OVER (ORDER BY [ID]) AS PrvVal
FROM tablename) tbl
WHERE [name] = 'A'
AND prvval <> 'A'
Online Demo: http://www.sqlfiddle.com/#!18/a55eb/2/0
If you want to get the whole row, you can do this...
SELECT Top 1 *
FROM (SELECT [name], [ID],
Lag([name]) OVER (ORDER BY [ID]) AS PrvVal
FROM tablename) tbl
WHERE [name] = 'A' AND prvval <> 'A'
ORDER BY [ID] DESC
Online Demo: http://www.sqlfiddle.com/#!18/a55eb/22/0
The ANSI SQL below uses a self-join on the previous id.
And the where-clause gets those with a name that's different from the previous.
select max(t1.ID) as ID
from YourTable as t1
left join YourTable as t2 on t1.ID = t2.ID+1
where (t1.name <> t2.name or t2.name is null)
and t1.name = 'A';
It should work on most RDBMS, including MS Sql Server.
Note that with the ID+1 that there's an assumption that are no gaps between the ID's.