Replacing the IN operator in Power BI RLS - sql

I want to ask if its possible to use something like IN operator in Power BI RLS DAX.
The approach I am using now seems very convoluted to me, and I want to ask if it could be done better and simpler.
I have two types of identifiers in my Fact table: Code and GroupCode. Code is NOT NULL identifier and can have multiple unique GroupCodes and GroupCode can be NULL and can be assigned to multiple Code.
Example Fact table:
Code
GroupCode
Client
1
a
John
1
b
Susie
1
c
Mark
2
a
John
2
NULL
Mary
3
b
Susie
I want to create report where User enters by Code, but see all rows with it GroupCode.
In SQL it would be:
SELECT * FROM table
WHERE GroupCode IN (SELECT GroupCode FROM TABLE WHERE Code = '2') or Code = '2'
For now I created Dictionary table from my Fact table with Code and CodeDict, where CodeDict = ISNULL(GroupCode, Code). Also added CodeDict column to Fact table to create relation based on it, between Dict and Fact tables. Should be (1:*), but it shows (*:*).
Example Dict table:
Code
GroupCode
1
a
1
b
1
c
2
a
2
2
3
b
As for RLS rule it is set on Dict table as [Code] = #USERPRINCIPALNAME().
So for example if User open report using Code = 2. RLS will filter Dict table so CodeDict will be (a, 2) and by them, it will filter Fact table to shows rows with Code=(1, 2)
It's very convoluted approach and I don't like it, but I have no idea I could make it other way. I worry about (*:*) relation and that I have to create Bridge Dict table.
What do you think about this approach to this problem?
Is there a way to implement IN operator in RLS rule?

Related

How can I have UNION respect column aliases?

Sorry for the bad title, I couldn't think of anything better. Feel free to edit.
I have to work with a db table that uses one column to store different types of information (last name if person, company name if company). A nightmare, I know, but it's what it is.
To distinguish the meaning, there is another column with an integer that specifies the type of what's in the name column.
The schema of this table looks as follows (simplified):
ID int
dtype int
name varchar(50)
So, a sample could look like this:
ID dtype name
---------------------------
1 0 Smith
2 0 Trump
3 1 ABC Ltd.
4 1 XYZ Ltd.
I'm trying to normalize this using the following T-SQL code:
WITH companies AS
(
SELECT ID, name AS company
FROM nametable WHERE dtype=1
),
people AS
(
SELECT ID, name AS person
FROM nametable WHERE dtype=0
),
SELECT * FROM companies UNION ALL SELECT * FROM people;
What I hoped to get is a new table with the schema:
ID
dtype
company
person
Or, in table view:
ID dtype person company
------------------------------------------
1 0 Smith
2 0 Trump
3 1 ABC Ltd.
4 1 XYZ Ltd.
Instead, the field is now just called person instead of name but it's still just one field for 2 types of information.
I understand I could just create a new table and insert each partial result into it but it seems there should be a simpler way. Any advice appreciated.
It seems you need case when which helps you
select ID, dtype,case when dtype=0 then name end AS company,
case when dtype=1 then name end AS person
FROM nametable
The CASE statement goes through conditions and return a value when condition is met, from your sample input and output its clear you want to create type wise new column ,so i used case Statement
You don't need to use UNION for this at all. A better approach would be using a bit of aggregation.
SELECT ID,
MAX(CASE WHEN dtype = 0 THEN [name] END) AS company
MAX(CASE WHEN dtype = 1 THEN [name] END) AS person
FROM nametable
GROUP BY ID;
UNION (ALL) doesn't "care" for aliases though. It combines the datasets it receives into 1. All the datasets must have the same definition and the dataset returned will have the same definition. If the datasets have different aliases for columns, the aliases supplied in the first dataset will be used. UNION doesn't detect that the datasets have different names for the columns and therefore return the different names as different columns; that's not what a UNION does.
Edit: well this will give the OP the data they want, however, there's no need for the aggregation. I was honestly expected ID's to be a shared resource; because that's normally the only time you have such horrid tables. The fact that it isn't just makes this table even more confused...

Access Append Query compare with table

I am currently rebuilding a messy Access Database and I entcountered the following problem:
I've got a Table of facilities which contain a row called district. Those Rows contain a number linked to another table which just contains the numbers and names of districts. I added a lookup Column with the Name of the district displayed.
I now want to change the new column for every row depending on the data in the old row.
Facilities
NAME|..|DISTRICT_OLD
A |..| 1
B |..| 2
C |..| 1
...
DISTRICTS
ID|NAME
1 |EAST
2 |WEST
...
I would like something like the following:
Facilities
NAME|..|DISTRICT_OLD|DISTRICT
A |..| 1|EAST
B |..| 2|WEST
C |..| 1|EAST
...
The District Field (lookup) gets its Data like follows SELECT [DISTRICTS].ID, [DISTRICTS].NAME FROM DISTRICTS ORDER BY [NAME];
(Thanks to Gordon Linoff) I could get the query but I do now struggle with the insert. I can get the Data I want:
SELECT [DISTRICTS].NAME FROM Facilities INNER JOIN DISTRICTS ON Facilities.DISTRICT_OLD = [DISTRICTS].ID;
If I try to INSERT INTO Facilities(DISTRICT) It says Typerror.
How can I modify the data to be compatible with a lookup column?
I guess I need to select the ID as well which isnt't a problem but then the error says to many columns.
I hope I haven't mistaken any names, my Access isn't running the english language.
Can you help me?
Fabian
Lookup columns are number (long integer)
with a relational database, you only need the single column containing the ID (as you always lookup the district.name with a query) so:
INSERT INTO Facilities(DISTRICT) SELECT 4
where 4 is the ID of the record in the lookup table that you want, or better still:
INSERT INTO Facilities(DISTRICT)
SELECT ID FROM DISTRICTS
where District.Name = "Name you want the ID for"

Creating a SQL view that contains columns which have different data types

I am trying to create a SQL view which contains columns from different tables; the columns are different data types.
For example;
I have table a with a column that contains usernames. The data type of this column is nvarchar.
I then have table b, which has a column that contains whether a document was printed in colour or not – the data is either yes or no. The data type of this column is bit.
I want the view to show both the above columns side by side, so I can then pull the information into Excel for reporting purposes.
I am pretty new to SQL so I am learning as I go along.
Like PM77-1 said, you'll have to have some way to tie the two tables together. For example, if your table b also has the userID of the person who printed the document out, your tables would look like this:
Table A Table B
---------------------------- -----------------------------------
userID userName docID docName inColor userID
---------------------------- -----------------------------------
1 userName1 1 docName1 1 1
2 userName2 2 docName2 0 2
3 userName3 1 docName1 1 2
3 docName3 0 1
3 docName3 1 2
2 docName2 1 3
and your query could look like this:
SELECT a.userName, b.docName, b.inColor FROM a INNER JOIN b ON a.userID = b.userID ORDER BY a.userName, b.inColor;

Normalise/join SQL Server tables

I have inherited a SQL server database which isn't normalised and is giving me headaches. I am not very experienced in SQL and maybe asking stupid questions but would appreciate any advice on how to go forward with the below scenarios.
I have three tables as follows:-
A table of results:
**ResId CompId Name Result**
1 1 Band A 2
2 1 Band B 1
3 1 Band C 3
4 2 Band A* 2
5 2 Band B 1
6 2 Band C 3
A table of Bands current names:
**BandId BandName**
1 Band A
2 Band B
3 Band C
A table of names the bands were previously known as (linked on BandId):
**oldBandId BandId oldBandName**
1 1 Band A*
2 1 Band a
2 2 Band b
I am looking to consolidate the list of band names in the results table, replacing the band name with a bandId however the result table contains band names from both tables. First question should I create some sort of join table and use this as the bandId in the results table? If so What do I need in this join table, is it just a psuedo-Id of bandId/oldBandId and the table name concatenated then this placed in the results table?
I am then looking to use a query to select all results where the user selects the band by any name variant (new or old) and returns the results including all names linked with the band i.e. choosing Band A would return the results for both Band A and Band A*.
Thanks in advance
Steve
I like the idea of using the band id in the results table. I would suggest eliminating the "old band name" table and replace it with a table of band aliases, since that sounds more like what you want. The band alias table would just have the band id and an one alias per row.
I think your current db structure is fine enough - I can't think of any way to improve on it, without complicating it further (especially if you want to retain the old band names).
You can just write a query as so for your need -
select * from results
where Name = #bandName or
Name in (select oldBandName
from oldBands
where BandId in (select BandId
from Bands
where BandName = #bandName))

Fetch a single field from DB table into itab

I want to fetch the a field say excep_point from a transparent table z_accounts for the combination of company_code and account_number. How can I do this in ABAP SQL?
Assume that table structure is
|company_code | account_number | excep_point |
Assuming you have the full primary key...
data: gv_excep_point type zaccounts-excep_point.
select single excep_point
into gv_excep_point
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
if you don't have the full PK and there could be multiple values for excep_point
data: gt_excep_points type table of zaccounts-excep_point.
select excep_point
into table gt_excep_points
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
There is at least another variation, but those are 2 I use most often.
For information only. When you selects data into table you can write complex expressions to combine different fields. For example, you have internal table (itab) with two fields "A" and "B". And you are going to select data from DB table (dbtab) wich have 6 columns - "z","x","y","u","v","w". And for example each field is type char2 You aim to cimbine "z","x","y","u" in "A" field of internal table and "v","w" in "B" field. You can write simple code:
select z as A+0(2)
x as A+2(2)
y as A+4(2)
u as A+6(2)
v as B+0(2)
w as B+2(2) FROM dbtab
INTO CORRESPONDING FIELDS OF TABLE itab
WHERE <where condition>.
This simple code makes you job done very simple
In addition to Bryans answer, here is the official online documentation about Open SQL.