SSRS Display display table groups side by side - reporting-services

Because I don't find a nice solution for my issue I hope to your expertise.
In a SSRS Report I have a dataset like this:
Tracking_Print_Right_Side
Tracking_Title_No
Tracking_Serial_No
Tracking_Lot_No
Nein
002
SN00043
CHARGE0015
Nein
002
SN00044
CHARGE0015
Nein
002
SN00045
CHARGE0015
Ja
002
SN00050
CHARGE0015
Ja
002
SN00051
CHARGE0016
Ja
002
SN00052
CHARGE0016
Nein
003
XYZ01125
CHARGE0017
Nein
003
XYZ01126
CHARGE0017
Nein
003
XYZ01127
CHARGE0017
Nein
003
XYZ01128
CHARGE0017
Ja
003
XYZ01135
CHARGE0017
Ja
003
XYZ01136
CHARGE0017
Ja
003
XYZ01137
CHARGE0017
Ja
003
XYZ01138
CHARGE0017
Expl.: Ja = True, Nein = False
As Result I will print it like this:
| | | False | True |
| 002 | CHARGE0015 | SN00043 | SN00050 |
| | | SN00044 | |
| | | SN00045 | |
| | CHARGE0016 | | SN00051 |
| | | | SN00052 |
| 003 | CHARGE0017 | XYZ01125 | XYZ01135 |
| | | XYZ01126 | XYZ01136 |
| | | XYZ01127 | XYZ01137 |
| | | XYZ01128 | XYZ01136 |
Row grouping on Tracking_Title_No and Tracking_Lot_No and a column grouping on Tracking_Print_Right_Side.
I can only create tables where the False and True Groups comes one after the other and not side by side.
How I should setup the tables?
The Tracking_Print_Right_Side is created by myself.
Mainly I will split the Charge group in the middle to save space in the report and use the whole width of the report.
Best regards
Bjoern

You can do this quite easily with a bit of work in SQL.
Here I have replicated your data and added a new column RowN which we can then use in the report to get the desired output.
Here's the full query
DECLARE #t TABLE (Tracking_Print_Right_Side sysname,Tracking_Title_No sysname, Tracking_Serial_No sysname, Tracking_Lot_No sysname)
INSERT INTO #t values
('Nein' , '002', 'SN00043', 'CHARGE0015'),
('Nein' , '002', 'SN00044', 'CHARGE0015'),
('Nein' , '002', 'SN00045', 'CHARGE0015'),
('Ja' , '002', 'SN00050', 'CHARGE0015'),
('Ja' , '002', 'SN00051', 'CHARGE0016'),
('Ja' , '002', 'SN00052', 'CHARGE0016'),
('Nein' , '003', 'XYZ01125', 'CHARGE0017'),
('Nein' , '003', 'XYZ01126', 'CHARGE0017'),
('Nein' , '003', 'XYZ01127', 'CHARGE0017'),
('Nein' , '003', 'XYZ01128', 'CHARGE0017'),
('Ja' , '003', 'XYZ01135', 'CHARGE0017'),
('Ja' , '003', 'XYZ01136', 'CHARGE0017'),
('Ja' , '003', 'XYZ01137', 'CHARGE0017'),
('Ja' , '003', 'XYZ01138', 'CHARGE0017')
SELECT
Tracking_Title_No
, Tracking_Lot_No
, Tracking_Print_Right_Side
, Tracking_Serial_No
, RowN = ROW_NUMBER() OVER(PARTITION BY Tracking_Print_Right_Side, Tracking_Lot_No, Tracking_Title_No ORDER BY Tracking_Serial_No)
FROM #t
This gives us the following results...
If we look at serial numbers SN00050 and SN00043 they both have RowN = 1
We can now use this to group by in the report.
Here's the report design including the row groups. NOTE I left the RowN column in for clarity but you don't need it, as long as the rowgroup is present you can remove the column.
When we run the report we get the following...

You can use a matrix instead of a table in SSRS

Related

Select 2 matching columns on base of 3rd column

I want to match id's of column 1 from column 2.
_________________________________
| uid | profile_id | status |
|------|-------------|-----------
| 1 | 2 | checked |
| 2 | 1 | checked |
| 3 | 4 | unchecked|
| 4 | 1 | unchecked|
| 4 | 3 | checked |
| 1 | 4 | checked |
...
This is my table. I want to show the result of same values that match from id1 to id2 and status is checked. Following is the output:
__________________________
| uid | profile_id | status |
|------|-------------|-----------
| 1 | 2 | checked |
| 2 | 1 | checked |
...
Because id1 1 check the id2 2 and vice versa.
I done the following code.
SELECT
`aa`.`uid` AS `uid`,
`aa`.`profile_id` AS `profile_id`,
`aa`.`match_type` AS `match_type`
FROM
(
`matched_profiles` `aa`
left join `matched_profiles` `ab` on(
(`aa`.`uid` = `ab`.`profile_id`)
)
)
where
(
(`aa`.`uid` = `ab`.`profile_id`)
and (`ab`.`uid` = `aa`.`profile_id`)
);
but above code also show me the unchecked result.
Great question. Because of the structure of the data int this table, you can do this by joining the table to itself. You will have two sets of data, replicas of one another.
You want to make sure there is a two-way match between uid and profile_id.
You also want the status for both directions to be checked
SELECT
a.*
FROM matched_profiles a
inner join matched_profiles a2 on
a.uid = a2.profile_id
and a.profile_id = a2.uid
and a.status = 'checked'
and a2.status = 'checked';
You have a kind of explicit/inexplicit join going on. I reformatted to be completely explicit for clarity. You just need to add a filter to make sure all status values are checked.
Below is the SQL to build your test schema, which is nice to provide when asking these questions for SO users.
create table matched_profiles (
uid int,
profile_id int,
status varchar(18)
);
insert into matched_profiles
values
(1, 2, 'checked'),
(2, 1, 'checked'),
(3, 4, 'unchecked'),
(4, 1, 'unchecked'),
(4, 3, 'checked'),
(1, 4, 'checked');

SQL - Is it possible to make custom column by row values?

Does anyone know if it's possible to turn something like the table below.. While still being able to use a SELECT query.
+----+-----------+---------------+------------+
| id | listingId | value | identifier |
+----+-----------+---------------+------------+
| 1 | 1a | Alaskan Husky | race |
| 2 | 1a | High | activity |
| 3 | 1a | White | colour |
| 4 | 1b | Akita | race |
| 5 | 1b | Medium | activty |
| 6 | 1b | Grey | colour |
+----+-----------+---------------+------------+
To something like this, while still being able to use a select query..
+----+-----------+---------------+---------+--------+
| id | listingId | race | activty | colour |
+----+-----------+---------------+---------+--------+
| 1 | 1a | Alaskan Husky | High | White |
| 2 | 1b | Akita | Medium | Grey |
+----+-----------+---------------+---------+--------+
I also want to be able to search this new "table". Let's say, the user has picked a filter with something like this:
Race: Alaskan Husky
Activity: Medium, High
It should then return the listingId of 1a.
The reason being for this, is that I can't do a proper SELECT query, when all the values are placed in different rows..
As you can see, the listingId should be the variable that groups it all together, and makes the value in the identifier column, a new column.
The reason why I don't just use the second table as default, is because each listing can have different filters and filter groups. And I need to be able to select specific listings that meet a user specified filter.
Thanks.
You can use conditional aggregation :
select min(id) id, listingId,
max(case when [identifier] = 'race' then [value] end) race,
max(case when [identifier] = 'activity' then [value] end) activity,
max(case when [identifier] = 'colour' then [value] end) colour
from table t
group by listingId;
This might do the trick, just a few self joins. I think there a few ways you could accomplish this but for me this is pretty easy to read and maintain.
CREATE TABLE [dbo].[the_table](
[id] [int] NULL,
[listingId] [varchar](50) NULL,
[value] [varchar](50) NULL,
[identifier] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT INTO the_table (id, listingId, value, identifier)
VALUES (1, '1a', 'alaskan huskey', 'race'),
(2, '1a', 'high', 'activity'),
(3, '1a', 'white', 'colour'),
(4, '1b', 'akita', 'race'),
(5, '1b', 'medium', 'activity'),
(6, '1b', 'grey', 'colour')
SELECT * FROM
(SELECT a.id, a.listingID, a.value AS race, b.value as activity, c.value as colour
FROM the_table a
INNER JOIN the_table b
ON a.listingId = b.listingId
INNER JOIN the_table c
ON a.listingId = c.listingId
WHERE a.identifier = 'race'
AND b.identifier = 'activity'
AND c.identifier = 'colour') AS t
WHERE t.colour = 'white'
Output:
You can achieve it using Pivot
DECLARE #MyTable TABLE (Id INT, listingId VARCHAR(20),Value VARCHAR(20), identifier varchar(20))
INSERT INTO #MyTable VALUES
(1,'1a','Alaskan Husky' ,'race'),
(2,'1a','High' ,'activity'),
(3,'1a','White' ,'colour'),
(4,'1b','Akita' ,'race'),
(5,'1b','Medium','activity'),
(6,'1b','Grey' ,'colour')
SELECT *
FROM
(
SELECT listingId, identifier,Value FROM #MyTable)t
PIVOT(MIN(Value)
FOR identifier
IN (race,activity,colour)
)p

use some default value in arithmetic operation if no row is found

I have got two tables:
booking(advertiser_id, name, bookings, on_date)
click(advertiser_id, name, clicks, on_date)
I need to find bookings/clicks for each name, advertiser_id-wise and date-wise. I was doing the following to achieve this:
select b.name, b.advertiser_id, max(b.bookings)/max(c.clicks), b.on_date from click c inner join booking b on
c.advertiser_id = b.advertiser_id and
c.name = b.name and
c.on_date = b.on_date
group by
b.name,
b.advertiser_id,
b.on_date
I need to return 0, if there are no bookings (no entry in booking table) for that specific click. How can I achieve this?
Example:
click table:
name clicks on_date advertiser_id
uk 123 2018-05-01 12
us 123 2018-05-02 12
us 123 2018-05-01 12
booking table:
advertiser_id name bookings on_date
12 uk 1200 2018-05-07
12 us 123 2018-05-07
12 uk 123 2018-05-01
12 us 123 2018-05-01
Result:
name advertiser_id max(b.bookings)/max(c.clicks) on_date
uk 12 1.0000 2018-05-01
us 12 1.0000 2018-05-01
Expected:
name advertiser_id max(b.bookings)/max(c.clicks) on_date
uk 12 1.0000 2018-05-01
us 12 1.0000 2018-05-01
us 12 0 2018-05-02
Note
I used max as to use columns which were not present in group by.
Something to think about...
DROP TABLE IF EXISTS click;
CREATE TABLE click
(name CHAR(2) NOT NULL
,clicks INT NOT NULL
,on_date DATE NOT NULL
,advertiser_id INT NOT NULL
,PRIMARY KEY(name,on_date,advertiser_id)
);
INSERT INTO click VALUES
('uk',123,'2018-05-01',12),
('us',123,'2018-05-02',12),
('us',123,'2018-05-01',12);
DROP TABLE IF EXISTS booking;
CREATE TABLE booking
(advertiser_id INT NOT NULL
,name CHAR(2) NOT NULL
,bookings INT NOT NULL
,on_date DATE NOT NULL
,PRIMARY KEY(advertiser_id,name,on_date)
);
INSERT INTO booking VALUES
(12,'uk',1200,'2018-05-07'),
(12,'us', 123,'2018-05-07'),
(12,'uk', 123,'2018-05-01'),
(12,'us', 123,'2018-05-01');
select c.name
, c.advertiser_id
, COALESCE(b.bookings,0)
, c.clicks
, c.on_date
from click c
left
join booking b
on c.advertiser_id = b.advertiser_id
and c.name = b.name
and c.on_date = b.on_date;
+------+---------------+------------------------+--------+------------+
| name | advertiser_id | COALESCE(b.bookings,0) | clicks | on_date |
+------+---------------+------------------------+--------+------------+
| uk | 12 | 123 | 123 | 2018-05-01 |
| us | 12 | 123 | 123 | 2018-05-01 |
| us | 12 | 0 | 123 | 2018-05-02 |
+------+---------------+------------------------+--------+------------+
You can do this using LEFT JOIN, So your query should look like,
select C.name,c.advertiser_id, IFNULL(max(b.bookings)/max(c.clicks), 0),c.on_date
FROM click c
LEFT join booking b on
c.advertiser_id = b.advertiser_id and
c.name = b.name and
c.on_date = b.on_date
group by
b.name,
b.advertiser_id,
b.on_date
And it's working perfectly.
Open LINK to see the output.

MYSQL - Selecting multiple rows in a single row

I have a table in MYSQL named as permit_bills which contains columns as bill_no, alcohol_typ, origin, 2000ml, 1000ml, bill_date. Table is shown below:
+---------+--------------+---------+--------+--------+-----------+
| bill_no | alcohol_typ | origin | 2000ml | 1000ml | bill_date |
+---------+------------- + --------+--------+--------+-----------+
| 2001 | s | f | 2 | 1 |01-02-2017 |
| 2001 | m | w | 3 | 4 |01-02-2017 |
+---------+--------------+---------+--------+--------+-----------+
I want to select all rows from above table into a single row based on their bill_no and bill_date and want to display the columns of 2000ml and 1000ml as per their alcohol_typ and `origin.
My output table must be like this:
+---------+--------------+-------------+------------+------------+-----------+
| bill_no | s_f_2000ml | s_f_1000ml | m_w_2000ml | m_w_1000ml | bill_date |
+---------+------------- + ------------+------------+------------+-----------+
| 2001 | 2 | 1 | 3 | 4 |01-02-2017 |
+---------+--------------+-------------+------------+------------+-----------+
Try this (pivot) query -
SELECT
bill_no,
MAX(IF(alcohol_typ = 's' AND origin = 'f', `2000ml`, NULL)) AS s_f_2000ml,
MAX(IF(alcohol_typ = 's' AND origin = 'f', `1000ml`, NULL)) AS s_f_1000ml,
MAX(IF(alcohol_typ = 'm' AND origin = 'w', `2000ml`, NULL)) AS m_w_2000ml,
MAX(IF(alcohol_typ = 'm' AND origin = 'w', `1000ml`, NULL)) AS m_w_1000ml,
bill_date
FROM permit_bills
GROUP BY bill_no, bill_date
Are you sure your output table needs to look like that?
You may be able to use the GROUP_CONCAT function instead which is sometimes an amazingly useful tool. You will need to split or explode the values in your application, but it might be all you need.
https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat

mySql query - subtract resulted value

I need a bit of help on a mathematical function,
Following query will result 2 lines per lot like this:
group | style | lot | section | q1 | q2 |q3 | q4 | ...
aaaaa | sssss | 123 | 111111 | 55 | 77 | 88 | 99 | ...
aaaaa | sssss | 123 | 222222 | 10 | 20 | 20 | 10 | ...
aaaaa | sssss | 321 | 111111 | 11 | 22 | 44 | 55 | ...
aaaaa | sssss | 321 | 222222 | 10 | 23 |33 | 10 | ...
each lot result 2 diff section code (2 lines)
Question is : how do I make a subtraction between the 2 section code for the colums q1 q2 q3 q4 q5 ... ?
expected results:
group | style | lot | q1 | q2 |q3 | q4 | ...
aaaaa | sssss | 123 | 45 | 57 |68 | 89 | ...
aaaaa | sssss | 321 | 1 | -1 |11 | 45 | ...
query so far :
SELECT DISTINCT gp_style_gr.code_groupe, po_lot.num_style, po_lot_sp.Num_lot,
po_lot_sp.num_secti, po_lot_se.code_secti, po_lot.terminer, po_lot.date_livraison,
po_lot_sp.qte_1, po_lot_sp.qte_2, po_lot_sp.qte_3, po_lot_sp.qte_4, po_lot_sp.qte_5,
po_lot_sp.qte_6, po_lot_sp.qte_7, po_lot_sp.qte_8, po_lot_sp.qte_9, po_lot_sp.qte_10,
po_lot_sp.qte_11, po_lot_sp.qte_12, po_lot_sp.qte_13, po_lot_sp.qte_14, po_lot_sp.qte_15,
po_lot_sp.qte_16, po_lot_sp.qte_17, po_lot_sp.qte_18, po_lot_sp.qte_19, po_lot_sp.qte_20,
po_lot_sp.qte_21, po_lot_sp.qte_22, po_lot_sp.qte_23, po_lot_sp.qte_24, po_lot_sp.qte_25,
po_lot_sp.qte_26, po_lot_sp.qte_27, po_lot_sp.qte_28, po_lot_sp.qte_29, po_lot_sp.qte_30
FROM po_lot_sp
LEFT OUTER JOIN po_lot_se ON po_lot_se.num_lot = po_lot_sp.num_lot
and po_lot_se.num_secti = po_lot_sp.num_secti
LEFT OUTER JOIN po_lot ON po_lot.num_lot = po_lot_sp.num_lot
LEFT OUTER JOIN gp_style_gr ON gp_style_gr.num_style = po_lot.num_style
WHERE
((gp_style_gr.code_groupe = 'INSTOCK') and (po_lot.terminer = '0')
and (po_lot_se.code_secti = '01')) or ((gp_style_gr.code_groupe = 'INSTOCK')
and (po_lot.terminer = '0') and (po_lot_se.code_secti = '09'))
ORDER BY gp_style_gr.code_groupe, po_lot.num_style, po_lot_sp.Num_lot,
po_lot_sp.num_secti, po_lot_se.code_secti, po_lot.terminer, po_lot.date_livraison,
Thanks !
If the section code follows some pattern as it does in your example, then you can simply join the table against itself.
I'll pretend your table is called po_lot_sp as it is in your example.
In the following query, I assume that the second row has a higher section number. That's the condition t1.section > t2.section. If not, change appropriately. If the section numbers follow no pattern, then ignore this completely.
SELECT t1.`group`, t1.style, t1.lot, t1.section,
t2.q1 - t1.q1 q1, t2.q2 - t1.q2 q2, t2.q3 - t1.q3 q3, t2.q4 - t1.q4 q4
FROM t t1
JOIN t t2 ON t1.`group` = t2.`group` AND t1.style = t2.style AND
t1.lot = t2.lot AND t1.section > t2.section
Fiddle here.
This is the fastest way I can think of. Of course, this is assuming that you want to decrement from section with value '111111':
SELECT `group`, style, lot,
sum(if(section = '111111', q1, -q1)),
sum(if(section = '111111', q2, -q2)),
sum(if(section = '111111', q3, -q3)),
sum(if(section = '111111', q4, -q4))
FROM t
GROUP BY `group`, style, lot
Fiddle here.
By the way, try not to use group as a column name. It is a reserved word.
If you don't know the section value you want to decrement from and you only want to decrement from the lowest section, then go for Andy's solution.
Try this:
select a.group,a.style,a.lot,
coalesce(a.q1 -
(select b.q1 from tablename b where b.ID = a.ID + 1), a.q1) as q1,
coalesce(a.q2-
(select b.q2 from tablename b where b.ID = a.ID + 1), a.q2) as q2,
coalesce(a.q3-
(select b.q3 from tablename b where b.ID = a.ID + 1), a.q3) as q3,
coalesce(a.q4-
(select b.q4 from tablename b where b.ID = a.ID + 1), a.q4) as q4
from tablename a group by a.lot
Note: Here ID refers to a primary key from your table and tablename refers to your original table name.So replace the field ID with your primary key field and table name vice-versa.
Demo