SSRS - Lookup only on certain columns in a matrix - reporting-services

I have a matrix table with a column group "Application questions" let's say these are in table 1. Some of the questions have unique string values such as: Name, ID number, email address. But others have an integer value that relates to an actual value for a separate lookup table (table 2), for example, the values for the column "Gender" are 1, 2, 3, for Male, Female, Other. Is there a way in the lookup function that I can isolate the columns that only have integer values or alternatively ignore the other columns with unique string values?
Table1
NAME ATTRIBUTE_id ATTRIBUTE
-----------------------------------------
James 5 1
James 6 james#email.com
James 7 8
Table2
Lookup_id ATTRIBUTE_id Description
-----------------------------------------
1 5 Male
2 5 Female
3 5 Other
8 7 New York
9 7 Los Angeles
Output
NAME | Email | Gender | City
-------------------------------------------------------
James james#email.com Male New York
Hope that makes sense!
Thank you.

I think this will be easier to do in your dataset query.
Below I have recreated your sample data and added an extra person in to make sure it's working as expected.
DECLARE #t TABLE (Name varchar(10), AttributeID INT, AttributeMemberID varchar(50))
INSERT INTO #t VALUES
('Mary', 5, '2'),
('Mary', 6, 'Mary#email.com'),
('James', 5, '1'),
('James', 6, 'james#email.com'),
('James', 7, '8')
DECLARE #AttributeMembers TABLE (AttributeMemberID INT, AttributeID int, Description varchar(20))
INSERT INTO #AttributeMembers VALUES
(1, 5, 'Male'),
(2, 5, 'Female'),
(3, 5, 'Other'),
(8, 7, 'New York'),
(9, 7, 'Los Angeles')
I also added in a new table which describes what each attribute is. We will use the output from this as column headers in the final SSRS matrix.
DECLARE #Attributes TABLE(AttributeID int, Caption varchar(50))
INSERT INTO #Attributes VALUES
(5, 'Gender'),
(6, 'Email'),
(7, 'City')
Finally we join all three togther and get a fairly normalised view for the data. The join is a bit messy as your current tables use the same column for both integer based lookups/joins and absolute string values. Hence the CASE in the JOIN
SELECT
t.Name,
a.Caption,
ISNULL(am.[Description], t.AttributeMemberID) as Label
FROM #t t
JOIN #Attributes a on t.AttributeID = a.AttributeID
LEFT JOIN #AttributeMembers am
on t.AttributeID = am.AttributeID
and
CAST(CASE WHEN ISNUMERIC(t.AttributeMemberID) = 0 THEN 0 ELSE t.AttributeMemberID END as int)
= am.AttributeMemberID
ORDER BY Name, Caption, Label
This gives us the following output...
As you can see, this will be easy to put into a Matrix control in SSRS.
Row group by Name, Column Group by Captionand data cell would beLabel`.
If you wanted to ensure the order of the columns, you could extend the Attributes table to include a SortOrder column, include this in the query output and use this in SSRS to order the columns by.
Hope that's clear enough.

Related

Power BI report Builder - Divide overflowing matrix row

I have a dynamic row of attributes associated with customer. Number of attributes for each customer may vary from 3 to n.
I am trying to display it in a row but if number of attributes increase from 3 to 10 data over flows from right to left on a page. For example
Attribute 1 | Attribute 2 | Attribute 3 | Attribute 4 | Attribute 5 | Attribute 6 | Attribute 7
Is it possible to start a new row for attributes after fixed number of columns, lets say 4?
Attribute 1 | Attribute 2 | Attribute 3 | Attribute 4
Attribute 5 | Attribute 6 | Attribute 7
I found similar question Table not overflowing properly - Power BI Report Builder but steps mentioned in answer are not clear.
Edit:
Design view:
Report View
TEST
I tried adding colum/row groups but doing that creates a matrix like this
Desired View
first 4 attributes to be rendered on 1st row and next 3 attributes to be rendered on second row
The way I would normally do something like this is to calculate the row and column numbers in the dataset query, then you can use these values as the row and column groups.
The following query creates some sample data, just ID and Attribute and then returns that same data along side the RowN and ColN columns which hold the row and column numbers respectively.
I've also parameterised this so you can easily adjust the number of generated columns.
The sample data contains data for 3 unique IDs, each with a different number of attributes.
Note: the attributes are named such they can be ordered alphabetically, you may have to adjust the three instances of the ORDER BY clause to get the order correct with your real data (if it matters).
DECLARE #t TABLE (ID int, Attribute varchar(20))
INSERT INTO #t VALUES
(1, 'Attribute 01'), (1, 'Attribute 02'), (1, 'Attribute 03'),
(2, 'Attribute 01'), (2, 'Attribute 02'), (2, 'Attribute 03'), (2, 'Attribute 04'), (2, 'Attribute 05'),
(3, 'Attribute 01'), (3, 'Attribute 02'), (3, 'Attribute 03'), (3, 'Attribute 04'), (3, 'Attribute 05'), (3, 'Attribute 06'), (3, 'Attribute 07'), (3, 'Attribute 08'), (3, 'Attribute 09'), (3, 'Attribute 10'), (3, 'Attribute 11')
DECLARE #MaxCols int = 5
SELECT
ID, Attribute,
RowN = (ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Attribute)-1) / #MaxCols,
ColN = (ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Attribute)-1) - (((ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Attribute)-1) / #MaxCols) * #MaxCols)
FROM #t
This gives us the following results (clipped for brevity)
Now we can create a simple matrix as per the design below. (Note the two row groups and one column group)
You can remove the RowN column (but not the group), I left it in for clarity..
When we run the report using 5 as the #MaxCols value we get this..
and settings the #MaxCols value to 4 gives us this.

How to select a mysql column values which contains Y first and N second

I want query in mysql to select a column values which contains Y and N.
Below is my table
If I use this query
"SELECT * from hotel where standard='Y' OR standard='N' group by hotel_code";
This query is working based on insert id but my requirement is not like that, first it should select 'Y' first then only 'N' should come.
[![enter image description here][3]][3]
I want select particular these column values
2 ---- 123 ------Y
4 -----324 ------Y
6 -----456 ------N or 5 ------456 -- N any row from when N appear
7 -----987 ------Y
Thanks in advance!!!
My previous answer has a problem which indicated error related to only_full_group_by when executing a query in MySql. However, I have created a local database myself and then came up with the correct sql that you need. Here it is.
SELECT min(origin), hotel_code, max(standard) as std from hotel
where standard='Y' OR standard='N'
group by hotel_code
order by std desc;
And after executing the sql, here's the result that I have got.
1 123 Y
3 324 Y
7 987 Y
5 456 N
I am sharing the create table and insert statements so that anyone can check by themselves if the query is okay.
create table hotel (
origin integer auto_increment primary key,
hotel_code integer not null,
standard varchar(1) not null
);
INSERT INTO `hotel` (`origin`, `hotel_code`, `standard`)
VALUES
(1, 123, 'Y'),
(2, 123, 'N'),
(3, 324, 'N'),
(4, 324, 'Y'),
(5, 456, 'N'),
(6, 456, 'N'),
(7, 987, 'N'),
(8, 987, 'Y');
Hope that helps!
Here what you need:
SELECT origin, hotel_code, CASE COUNT(DISTINCT standart)
WHEN 1 AND standart = "N" THEN "N"
WHEN 1 AND standart = "Y" THEN "Y"
WHEN 2 THEN "Y"
END as standart
FROM hotel
GROUP BY hotel_code ORDER BY standart DESC
Results:
origin hotel_code standart
1 123 Y
3 324 Y
9 888 Y
7 987 Y
6 456 N
SQLFiddle: http://sqlfiddle.com/#!9/17bd53/3/0
There are many approaches to solve your algorithm, however, due to simplicity I pick this one:
SELECT h2.origin, h2.hotel_code, h2.standard
FROM (SELECT * FROM hotel WHERE standard = 'Y') h1
JOIN hotel h2 on h1.hotel_code = h2.hotel_code
ORDER BY h2.hotel_code, h2.standard;
Click here to view it working
Enjoy it!

SQL Query for exact match in many to many relation

I have the following tables(only listing the required attributes)
medicine (id, name),
generic (id, name),
med_gen (med_id references medicine(id),gen_id references generic(id), potency)
Sample Data
medicine
(1, 'Crocin')
(2, 'Stamlo')
(3, 'NT Kuf')
generic
(1, 'Hexachlorodine')
(2, 'Methyl Benzoate')
med_gen
(1, 1, '100mg')
(1, 2, '50ml')
(2, 1, '100mg')
(2, 2, '60ml')
(3, 1, '100mg')
(3, 2, '50ml')
I want all the medicines which are equivalent to a given medicine. Those medicines are equivalent to each other that have same generic as well as same potency. In the above sample data, all the three have same generics, but only 1 and three also have same potency for the corresponding generics. So 1 and 3 are equivalent medicines.
I want to find out equivalent medicines given a medicine id.
NOTE : One medicine may have any number of generics. Medicine table has around 102000 records, generic table around 2200 and potency table around 200000 records. So performance is a key point.
NOTE 2 : The database used in MySQL.
One way to do it in MySQL is to leverage GROUP_CONCAT() function
SELECT g.med_id
FROM
(
SELECT med_id, GROUP_CONCAT(gen_id ORDER BY gen_id) gen_id, GROUP_CONCAT(potency ORDER BY potency) potency
FROM med_gen
WHERE med_id = 1 -- here 1 is med_id for which you're trying to find analogs
) o JOIN
(
SELECT med_id, GROUP_CONCAT(gen_id ORDER BY gen_id) gen_id, GROUP_CONCAT(potency ORDER BY potency) potency
FROM med_gen
WHERE med_id <> 1 -- here 1 is med_id for which you're trying to find analogs
GROUP BY med_id
) g
ON o.gen_id = g.gen_id
AND o.potency = g.potency
Output:
| MED_ID |
|--------|
| 3 |
Here is SQLFiddle demo

Query to get categorised sets of splits

Given this table structure:
CREATE TABLE IF NOT EXISTS splits (
id INT AUTO_INCREMENT,
sector_id INT,
type VARCHAR(100),
percentage INT,
PRIMARY KEY (id),
INDEX (type)
) ENGINE MyISAM;
And this data set:
INSERT INTO splits (sector_id, type, percentage) VALUES
(1, 'Manager', '50'),
(1, 'Sales Rep', '50'),
(2, 'Manager', '75'),
(2, 'Sales Rep', '25'),
(3, 'Manager', '75'),
(3, 'Sales Rep', '25'),
(4, 'Manager', '100'),
(5, 'Manager', '100'),
(6, 'Manager', '100');
How could I return the amount of sectors that split in the same way:
Like this:
Split | Number
---------------+-------
50% M / 50% SR | 1
75% M / 25% SR | 2
100% M | 3
So this shows 1 sector (id 1) has a split ratio of 50/50, 2 sectors have a split ratio of 75/25 (ids 2, 3) and 3 sectors have a split ratio off 100/0 (ids 4, 5, 6).
Here is a SQL Fiddle with the database setup: http://sqlfiddle.com/#!2/6b19f/1
What have you tried?
I cannot even think of where to start to solve this problem, so I apologise for not being able to show an attempted solution. I will update this question if I get anywhere.
The reason why I want to do this all in the database (and not the application) is because our automated reporting tools can be pointed to a table/view/query and automatically apply filtering, sorting, charting etc. To do it manually in the application loses all the default functionality.
I don't really understand the problem. Your DB contains already all the data you want to retrieve?!
SELECT
sector_id AS Number,
type
percentage
FROM
splits
The easiest thing would now to take you software and then turn those (type-percentage)-tuples into strings. Why do you need the database to create and concat this string?
Can there be more than 2 types?
For Postgres I'd use an array of tuples for output:
SELECT
sector_id,
array_agg(row(percentage, type))
FROM
splits
GROUP BY
sector_id
Correct Query:
SELECT
x.y,
COUNT(*) c
FROM (
SELECT
sector_id,
GROUP_CONCAT(CONCAT(percentage, '% '), type SEPARATOR ' / ') AS y
FROM (
SELECT
sector_id,
type,
percentage
FROM splits
ORDER BY sector_id, type
) z
GROUP BY sector_id
) x
GROUP BY x.y
ORDER by c
Result will look like this:
50% Manager / 50% Sales Rep | 1
75% Manager / 25% Sales Rep | 2
100% Manager | 3

return rows where sum on a field less than a given value

My knowledge of MySQL is basic. I want to build a query to return all rows that sum a given value, in ascending order. I can't figure out how I can do that. Using sum() only returns one row. I've tried a subquery but it returns all rows. I don't want anybody do my work, I just want you to help me to figuring this out.
Anybody have an idea?
How to retrieve all rows that its filed "value" sum 30
Example:
given value: 30
field to sum: value
table:
id name value order
1 name1 3 1
2 name2 10 6
3 name3 13 3
4 name4 5 8
5 name5 20 25
So, the query must return:
id 1, id 3, id 2, id 4
Thanks in advance.
set #total:=0;
select id, name, value, `order`
from
(select
id, name, value, `order`,
#total:=if(#total is null, 0, #total)+`order` as total
from THE_TABLE
order by `order`
) as derived
where total<=30;
Using postgres as database, I think this does what you want. I'm not sure if it works similar in mysql:
CREATE TABLE test (
id int,
name varchar(50),
value int,
order_ int
);
INSERT INTO test values (1, 'name1', 3, 1);
INSERT INTO test values (3, 'name3', 13, 3);
INSERT INTO test values (2, 'name2', 10, 6);
INSERT INTO test values (4, 'name4', 5, 8);
INSERT INTO test values (5, 'name5', 20, 25);
SELECT * FROM (SELECT *, SUM(value) OVER (ORDER BY order_) sumvalues FROM TEST) a WHERE sumvalues <30