Converting a DAX expression to an SSRS expression - reporting-services

I have these two expressions to convert from DAX expressions to SSRS expressions, I am trying to replicate this expression in an ssrs environment to determine the metrics as shown below. I quite understand the expression but finding the appropriate expression to articulate this expression in ssrs seems to be the issue
ABS (
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" ) )
) < 1,
BLANK (),
DIVIDE (
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" ) ),
CALCULATE ( [CashAmount], PATHCONTAINS ( 'Account'[Account Hierarchy], "XYZ" ) )
)
) * -1 ```
and ```CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "ABC" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "EFG" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "HIJK" )
)
)
+ CALCULATE (
[CashAmount],
FILTER (
ALL ( 'Account' ),
PATHCONTAINS ( 'Account'[Account Hierarchy], "LMNO" )
)
) ```

Related

Extract a field from a column (in json) and Concat them in SQL Server

I want to extract and concat a field in a json column .
I have a table with two field :
id
JsonColumn
In the json Column i can have x object which contains 2 fields (Name and Type)
For Example, in my table I can have :
What i want to do is to extract and concat the field Name in a json colum.
So i will have :
Don't hesitate to share your opinion.
(I was thinking about a big loop with openJson but i fear that the query will be very long after that).
You need to parse the JSON content using OPENSJON() to extract the "Name" key and then aggregate the values. For SQL Server 2016 you need to use FOR XML PATH for aggregation.
Table:
SELECT Id, JsonColumn
INTO Data
FROM (VALUES
(1, '[{"Name": "Matthew", "Type":"Public"}, {"Name": "Rachel", "Type":"Private"}]'),
(2, '[{"Name": "Sample", "Type":"Private"}]')
) v (Id, JsonColumn)
Statement:
SELECT
Id,
Name = STUFF(
(
SELECT ',' + Name
FROM OPENJSON(JsonColumn) WITH (Name varchar(100) '$.Name')
FOR XML PATH('')
), 1, 1, ''
)
FROM Data
Result:
Id JsonColumn
------------------
1 Matthew,Rachel
2 Sample
Rough approach (currently not enough time for me to provide working SQL to code).
To do it in one step (best as view) use the CTE approach to stagger the steps. This generates more code and over time allows easier amendments. It is a trade off.
Recursive approach
First step:
Extract relational records with ID and names. Use OPENJSON WITH a defined table structure where only the Name is extracted (rest can be ignored or left as additional JSON).
Second step:
Use the output from first step and turn into recursive concatenation. Using a variable to concatenate to forces the use of a procedure. Doing it in a view requires definition of anchor and end conditions. Not quite sure on this as it is tricky.
In a CTE part this requires an anchor element union'ed with all other elements. In effect this groups by the selected key field(s).
Third step:
Output of the finished recursion by key field(s).
Quick demo code
DECLARE
#Demo TABLE
(
id_col tinyint identity(1,1),
dsc_json nvarchar(max)
)
;
INSERT INTO
#Demo
(
dsc_json
)
SELECT N'[{"Name":"Celery","Type":"Vegetable"}, {"Name":"Tomato","Type":"Fruit"}]'
UNION
SELECT N'[{"Name":"Potato","Type":"Vegetable"}]'
UNION
SELECT N'[{"Name":"Cherry","Type":"Fruit"}, {"Name":"Apple","Type":"Fruit"}]'
;
SELECT
*
FROM
#Demo
;
-- extract JSON
SELECT
demo.id_col,
jsond.dsc_name,
Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name ASC ) AS val_row_asc,
Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name DESC ) AS val_row_desc
FROM
#Demo AS demo
CROSS APPLY OPENJSON( demo.dsc_json )
WITH
(
dsc_name nvarchar(100) '$.Name'
) AS jsond
;
WITH
cte_json
(
id_col,
dsc_name,
val_row_asc,
val_row_desc
)
AS
(
SELECT
demo.id_col,
jsond.dsc_name,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name ASC ) AS int ) AS val_row_asc,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name DESC ) AS int ) AS val_row_desc
FROM
#Demo AS demo
CROSS APPLY OPENJSON( demo.dsc_json )
WITH
(
dsc_name nvarchar(100) '$.Name'
) AS jsond
),
cte_concat
(
id_col,
dsc_names,
val_row_asc,
val_row_desc
)
AS
( -- anchor first
-- - emtpy string per ID
SELECT
anchor.id_col,
Cast( N'' AS nvarchar(500) ) AS names,
Cast( 0 AS int) AS val_row_asc,
Cast( -1 AS int ) AS val_row_desc
FROM
cte_json AS anchor
WHERE -- anchor criteria
val_row_asc = 1
UNION ALL
SELECT
anchor.id_col,
Cast( anchor.dsc_names + N', ' + element.dsc_name AS nvarchar(500) ) AS names,
element.val_row_asc,
element.val_row_desc
FROM
cte_json AS element
INNER JOIN cte_concat AS anchor
ON anchor.id_col = element.id_col
AND anchor.val_row_asc = element.val_row_asc -1
)
SELECT
cte.id_col,
Right( cte.dsc_names, Len( cte.dsc_names ) -2 ) AS dsc_names,
cte.val_row_desc
FROM
cte_concat AS cte
WHERE -- only latest result
cte.val_row_desc = 1
ORDER BY
cte.id_col ASC
;
The additional row numbers allow:
define start and end point for the recursive connection = val_row_asc
define "definition" of latest result = val_row_desc
Stuff ... for XML Path
This approach works on all versions and is much easier to read than the recursive part thanks to Zhorov's answer. Works on the base laid by the first part of the code above (or just straight afterwards).
WITH
cte_json
(
id_col,
dsc_name,
val_row_asc,
val_row_desc
)
AS
(
SELECT
demo.id_col,
jsond.dsc_name,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name ASC ) AS int ) AS val_row_asc,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name DESC ) AS int ) AS val_row_desc
FROM
#Demo AS demo
CROSS APPLY OPENJSON( demo.dsc_json )
WITH
(
dsc_name nvarchar(100) '$.Name'
) AS jsond
)
SELECT
cte_outer.id_col,
Stuff(
( SELECT
',' + cte_inner.dsc_name
FROM
cte_json AS cte_inner
WHERE
cte_inner.id_col = cte_outer.id_col
FOR XML PATH('')
), 1, 1, ''
) AS dsc_names
FROM
cte_json AS cte_outer
GROUP BY
cte_outer.id_col
;
String_agg
This approach only works with SQL Server 2017 onwards. It is a continuation to the code above.
WITH
cte_json
(
id_col,
dsc_name,
val_row_asc,
val_row_desc
)
AS
(
SELECT
demo.id_col,
jsond.dsc_name,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name ASC ) AS int ) AS val_row_asc,
Cast( Row_number() OVER ( PARTITION BY demo.id_col ORDER BY jsond.dsc_name DESC ) AS int ) AS val_row_desc
FROM
#Demo AS demo
CROSS APPLY OPENJSON( demo.dsc_json )
WITH
(
dsc_name nvarchar(100) '$.Name'
) AS jsond
)
SELECT
cte.id_col,
String_agg( cte.dsc_name, ',' ) AS dsc_names
FROM
cte_json AS cte
GROUP BY
cte.id_col
;

How can I use Math Formula in a MySQL query?

I am creating a CPM and I am trying to get all the CPM that are not on track. I have the follow code below and I have put the formula in the WHERE clause, but it shows all results. Instead of only results that are less than 0.9.
SELECT cpms.*, site_images.*
FROM ( cpm_images
INNER JOIN site_images ON ( cpm_images.site_image_id = site_images.site_image_id ) )
INNER JOIN cpms
ON
( cpms.cpm_id = cpm_images.cpm_id )
WHERE (
( cpms.cpm_views_count * ( $data - cpms.cpm_date_start ) ) /
( cpms.cpm_views_total * (cpms.cpm_date_end - $data ) )
) < 0.9
No matter what number is calculated it show the all the results. If the number is below 0.9 it shows, if it is above 0.9, it shows.
UPDATE:
the following data is what is being pulled from the datbase.
This is the data from the table.
[cpm_id] => 1
[cpm_title] => Ad Special
[cpm_date_start] => 1556746806
[cpm_date_end] => 1559425206
[cpm_views_total] => 1000
[cpm_views_count] => 500
[cpm_image] =>
[cpm_active] => 1
[site_image_id] => 137
[site_image_file] => cars/3.jpg
[site_image_file_tn] => cars/3.jpg
[site_image_file_org] => cars/3.jpg
[site_image_title] =>
[site_image_description] =>
[site_image_upload_date] => 0
When i places numbers in place of the table row names
( 500 * ( 1557665447 - 1559425206 ) )
/
( 1000 * ( 1556746806 - 1557665447 ) )
it works, so is it possible that the table row names are not showing as int. yet the table is as follows
`cpm_id` int(11) UNSIGNED NOT NULL,
`cpm_title` varchar(255) NOT NULL,
`cpm_date_start` int(11) NOT NULL,
`cpm_date_end` int(11) NOT NULL,
`cpm_views_total` int(11) NOT NULL,
`cpm_views_count` int(11) NOT NULL,
`cpm_image` varchar(255) DEFAULT NULL,
`cpm_active` int(1) DEFAULT NULL
if I have the numbers
( 0 * ( 1557665447 - 1559425206 ) ) / ( 1000 * ( 1556746806 - 1557665447 ) )
it equals to 0 so it shows as it is below 0.9
BUT if i have the follow
( 1000 * ( 1557665447 - 1559425206 ) ) / ( 1000 * ( 1556746806 - 1557665447 ) )
which equals to 1.91561121265 which it shows in the results, but it shouldn't as it is not smaller then 0.9
UPDATE:
if i use the follow
WHERE ( ( cpms.cpm_views_count * ( 1557665447 - 1559425206 ) ) / ( cpms.cpm_views_total * ( 1556746806 - 1557665447 ) ) ) < 0.9
It works, and the following works too
WHERE ( ( cpms.cpm_views_count * ( $date - 1559425206 ) ) / ( cpms.cpm_views_total * ( 1556746806 - $date ) ) ) < 0.9
but as soon as i change it to
WHERE ( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_start ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_end - $date ) ) ) < 0.9
it does not work, I even try putting brackets around cpms.cpm_date_end and cpms.cpm_date_start and it still failed.
I have found the issue, I had the cpm_views_start and cpm_views_end wrong way around
( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_end ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_start - $date) ) )
How I realized this was when I put it in as follows
SELECT ( ( cpms.cpm_views_count * ( $date - cpms.cpm_date_end ) ) / ( cpms.cpm_views_total * ( cpms.cpm_date_start - $date) ) ) AS sum_2
it came back a different number. I realize somewhere during coding the string I change the cpm_date_end and cpm_date_start around, yet in where i had it showing on the screen for testing, it was the correct way, so the data on the screen was correct but when it was calculating it in the query, it was wrong way about.
Thank you #nick for doing what you can to help me.

Inputting data from dataset to SSRS table

I am new to this and i am wondering how to input data into SSRS table and auto generate for the subsequent months. This is the format of the table.
Appreciated for any help given.
You can generate a date range using the following SQL
DECLARE #date_start AS DATETIME
SET #date_start = '01-DEC-2017'
;WITH
finalvalues
AS
(
SELECT tbl.* FROM (VALUES
( '01-Dec-2017', 6414.6563, 429.6846, -1390.8474)
, ( '02-Dec-2017', 6476.6563, 432.751, -1312.4928)
, ( '03-Dec-2017', 6538.6563, 435.8174, -1234.1382)
, ( '04-Dec-2017', 6600.6563, 438.8838, -1155.7836)
, ( '05-Dec-2017', 6662.6563, 441.9502, -1077.429)
, ( '06-Dec-2017', 6724.6563, 445.0166, -999.074399999999)
, ( '07-Dec-2017', 6786.6563, 448.083, -920.719799999999)
, ( '08-Dec-2017', 6848.6563, 451.1494, -842.365199999999)
, ( '09-Dec-2017', 6910.6563, 454.2158, -764.010599999999)
, ( '10-Dec-2017', 6972.6563, 457.2822, -685.655999999999)
, ( '11-Dec-2017', 7034.6563, 460.3486, -607.301399999999)
, ( '12-Dec-2017', 7096.6563, 463.415, -528.946799999999)
, ( '13-Dec-2017', 7158.6563, 466.4814, -450.592199999999)
, ( '14-Dec-2017', 7220.6563, 469.5478, -372.2376)
, ( '15-Dec-2017', 7282.6563, 472.6142, -293.883)
, ( '16-Dec-2017', 7344.6563, 475.6806, -215.5284)
) tbl ([Date], [IncLoad], [ITLoad], [RH])
)
,
manufactured_dates
AS
(
SELECT
day_date = DATEADD(day, dte.[number], #date_start)
FROM
master.dbo.spt_values AS dte
WHERE
1=1 -- <-- used in testing to be able to comment out other clauses below
AND dte.[type] = 'P'
AND dte.[number] <= 365 -- <-- filter how many rows you want to see here
)
SELECT
'Date' = md.[day_date]
, 'IncLoad' = AVG(incload)
, 'ITLoad' = AVG(ITLoad)
FROM
finalvalues AS fv
FULL OUTER JOIN manufactured_dates AS md ON md.[day_date] = fv.[Date]
GROUP BY
md.[day_date]

How to compare data from two tables in sql?

I have table like this:
table's name: registrationdate
I want to get the maximum value on last_update's column, so I use this query:
SELECT idtemp, max(last_update) FROM `registrationdate`
then the result will be like this:
and I have table like this:
table's name: temp
then I want to compare max(last_update) in registrationdate's table and generatedtime in temp's table
this is the schema:
what may I do so that I can get table like that? Thanks in advance.
Fyi, idtemp in registrationdate's table = id in temp's table
Please try the following...
SELECT ID AS ID,
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN generatedTime < maxLastUpdate THEN
'not'
ELSE
'update'
END AS UPDATEorNot
FROM temp
JOIN ( SELECT idtemp AS idtemp,
MAX( last_update ) AS maxLastUpdate
FROM registrationdate
GROUP BY idtemp
) AS maxLastUpdateFinder ON temp.ID = maxLastUpdateFinder.idtemp;
Assumptions
That records in temp that do not have at least one matching record in registrationdate do not need to be included in the output.
That the comparison and sample data are valid and the sample output's UPDATEorNot field should read not.
Explanation
This statement starts with a subquery that finds each unique value of idtemp in registrationdate and the most recent value of last_update associated with it.
An INNER JOIN is then performed between temp and the results of the subquery so that each record in temp with at least one corresponding record in registrationdate is retained and has its corresponding most recent value of last_update appended to it.
The fields from temp are then SELECTed, and a CASE statement used to determine the value to be selected for each record's UPDATEorNot field.
Please note that my statement will return not when the comparison that you supplied is applied to the sample data. If you want update to be chosen then you will need to change your comparison from generatedTime < max( last_update ) to generatedTime > max( last_update ), or to correct your sample data.
Testing
My statement was tested against a sample database created using the following script...
CREATE TABLE registrationdate
(
last_update DATETIME,
idtemp INT
);
INSERT INTO registrationdate ( last_update,
idtemp )
VALUES ( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 );
CREATE TABLE temp
(
ID INT,
generatedTime DATETIME,
tempTable VARCHAR( 50 )
);
INSERT INTO temp ( ID,
generatedTime,
tempTable )
VALUES ( 0, '2017-05-01 14:37:00', 'temp_pelamardoktorjk' ),
( 2, '2017-05-01 14:37:00', 'temp_pelamarmagisteripk' ),
( 3, '2017-05-01 14:38:00', 'temp_pelamarmagisterstatusinstitusi' ),
( 4, '2017-05-01 14:38:00', 'temp_pelamarmagisterusia' ),
( 5, '2017-05-01 14:38:00', 'temp_pelamarmagisterstatusinstansi' );
If you have any questions or comments, then please feel free to post a Comment accordingly.
Appendix 1
The following is an alternative form of the above statement...
SELECT ID AS ID,
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN generatedTime < MAX( last_update ) THEN
'not'
ELSE
'update'
END AS UPDATEorNot
FROM temp
JOIN registrationdate ON temp.ID = registrationdate.idtemp
GROUP BY ID,
generatedTime,
tempTable;
Appendix 2
Please try the following attempted rewrite of the linked to code...
SELECT
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN ( ( generatedTime < ( SELECT MAX( last_update ) AS maxPelamarmhsdoktor
FROM pelamarmhsdoktor ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxAkdmstmayor
FROM akdmst_mayor ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbmstdepartemen
FROM ipbmst_departemen ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbmstfakultas
FROM ipbmst_fakultas ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbrefjeniskelamin
FROM ipbref_jeniskelamin ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxJenisinstansi
FROM jenisinstansi ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxJenisinstitusi
FROM jenisinstitusi
) ) ) THEN
'Yes'
ELSE
'No'
END AS NeedsToUpdateOrNot
FROM generatedTime;

RANKING Function in DAX or MDX

How can i get result in attached image by DAX or MDX.Both can work for me.
( I will use DAX in Tabular Model and Will use MDX on SSRS part).
Sample Format
I tried below code but it didn't work.
WITH
SET OrderSet AS
Order
(
(
[Dim Product].[Category Name].[Category Name].MEMBERS
,[Dim Product].[Subcategory Name].[Subcategory Name].MEMBERS
,[Dim Product].[Sub Subcategory Name].[Sub Subcategory Name].MEMBERS
,[Dim Product].[Product Name].[Product Name].MEMBERS
)
,[Measures].[Order Quantity]
,BDESC
)
MEMBER [Measures].[RankOrderCount] AS
Rank
(
(
[Dim Product].[Category Name].CurrentMember
,[Dim Product].[Subcategory Name].CurrentMember
,[Dim Product].[Sub Subcategory Name].CurrentMember
,[Dim Product].[Product Name].CurrentMember
)
,OrderSet
)
SELECT
{
[Measures].[Order Quantity]
,[Measures].[RankOrderCount]
} ON 0
,NON EMPTY
{OrderSet} ON 1
FROM [Adventure Works DW2016CTP3];
I don't understand the problem. If I run this:
WITH
SET OrderSet AS
Order
(
(
[Product].[Category].[Category].MEMBERS
,[Product].[Subcategory].[Subcategory].MEMBERS
)
,[Measures].[Order Quantity]
,BDESC
)
MEMBER [Measures].[RankOrderCount] AS
Rank
(
(
[Product].[Category].CurrentMember
,[Product].[Subcategory].CurrentMember
)
,OrderSet
)
SELECT
{
[Measures].[Order Quantity]
,[Measures].[RankOrderCount]
} ON 0
,NON EMPTY
{OrderSet} ON 1
FROM [Adventure Works];
I get this:
This looks like your desired output format - but I did not change the script - so what is the question?
For example:
DEFINE
VAR TableTMP1 =
SELECTCOLUMNS (
DimProductTable,
"Product Name", DimProductTable[Product Name],
"Sub Subcategory Name", RELATED ( SubSubcategoryTable[Sub Subcategory Name] ),
"Subcategory Name", RELATED ( SubcategoryTable[Subcategory Name] ),
"Category Name", RELATED ( CategoryTable[Category Name] )
)
VAR TableTMP2 =
ADDCOLUMNS (
TableTMP1,
"Order Count", CALCULATE ( SUM ( OrderTable[Quantity] ) )
)
EVALUATE
ADDCOLUMNS ( TableTMP2, "Rank", RANKX ( TableTMP2, [Order Count], ASC ) )
ORDER BY [Rank] ASC