Thursday, December 22, 2016

Nutrition Facts Table in HTML & CSS

Nutrition Facts Table in HTML & CSS

CodePen Nutrition Facts Table in HTML CSS
Pricing tables, data tables, dynamic tables, there are so many ways to use tables, and one more to add to the list is the following template — a table data template for displaying nutrition facts for literally any food item out there. Of course, adding each of the facts standalone could take up some time, even just to report all the existing fruit there is, so we highly recommend to take this template and integrate it within your existing platform that requires to output nutritional information for produce, and then filter all your data through this template to provide a remarkable experience for anyone looking it up.
Download


source : https://colorlib.com/wp/css3-table-templates/

Wednesday, November 23, 2016

Monday, October 17, 2016

Passing multiple values for a single parameter in Reporting Services

Passing multiple values for a single parameter in Reporting Services


=join(Parameters!<your param name>.Value,",")
source : http://stackoverflow.com/questions/512105/passing-multiple-values-for-a-single-parameter-in-reporting-services

Wednesday, October 12, 2016

Center and crop thumbnails with CSS

Here is a handy CSS centering technique I first noticed in the WordPress media library, where it is used to centre and crop irregularly sized thumbnails within a square container.
cropped-thumbnails
The technique uses CSS3 transforms, so it works in all modern browsers, including IE9 and above.
<div class="thumbnail">
  <img src="landscape-img.jpg" alt="Image" />
</div>
<div class="thumbnail">
  <img src="portrait-img.jpg" class="portrait" alt="Image" />
</div>
.thumbnail {
  position: relative;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.thumbnail img {
  position: absolute;
  left: 50%;
  top: 50%;
  height: 100%;
  width: auto;
  -webkit-transform: translate(-50%,-50%);
      -ms-transform: translate(-50%,-50%);
          transform: translate(-50%,-50%);
}
.thumbnail img.portrait {
  width: 100%;
  height: auto;
}
The technique works by positioning the image so that its top left corner is in the centre of its container. Then, a 2D translation moves it up and left by half its own width.
The key here is that the percentage values passed to the translate function are relative to the element, not its container, as would be the case if we were to manipulate the element’s top andleft properties instead.
Note that the portrait format image has the class portrait, so that we can correctly scale it to fill its container.
So there you go. A really simple CSS technique for centering and cropping thumbnails.
Source : http://jonathannicol.com/blog/2014/06/16/centre-crop-thumbnails-with-css/

Friday, September 30, 2016

Tablix: Repeat header rows on each page not working

Tablix: Repeat header rows on each page not working


It depends on the tablix structure you are using. In a table, for example, you do not have column groups, so Reporting Services does not recognize which textboxes are the column headers and setting RepeatColumnHeaders property to True doesn't work.
Instead, you need to:
  1. Open Advanced Mode in the Groupings pane. (Click the arrow to the right of the Column Groups and select Advanced Mode.)
    • Screenshot
  2. In the Row Groups area (not Column Groups), click on a Static group, which highlights the corresponding textbox in the tablix. Click through each Static group until it highlights the leftmost column header. This is generally the first Static group listed.
  3. In the Properties window, set the RepeatOnNewPage property to True.
    • Screenshot
  4. Make sure that the KeepWithGroup property is set to After.
The KeepWithGroup property specifies which group to which the static member needs to stick. If set to After then the static member sticks with the group after it, or below it, acting as a group header. If set to Before, then the static member sticks with the group before, or above it, acting as a group footer. If set to None, Reporting Services decides where to put the static member.
Now when you view the report, the column headers repeat on each page of the tablix.
This video shows how to set it exactly as the answer described
source : http://stackoverflow.com/questions/11285923/tablix-repeat-header-rows-on-each-page-not-working-report-builder-3-0

Thursday, September 29, 2016

First and Last day of current month

=DateSerial(Year(Now), Month(Now), 1) for first day of the month 
=DateSerial(Year(Now), Month(Now)+1, 0) for the last day of the month.
--previous month last
=DateSerial(Year(Now()), Month(Now()), "1").AddDays(-1)

--previous month first
=DateSerial(Year(Now()), Month(Now()), "1").AddMonths(-1)

SSRS Expression Cheat Sheet

SSRS Expression Cheat Sheet

ProblemsExpression
Return first day of current Week 
(ex. Default Start Date parameter to return WTD)
Expression on the parameter default value: 
=DateAdd("d",-DatePart(DateInterval.WeekDay,Today,0,0)+1,Today) 
Expression Output Example: 11/7/2010 12:00:00 AM
Return first day of current Month 

(ex. Default Start Date parameter to return MTD)
Expression on the parameter default value: =DateAdd("d",-(Day(today)-1), Today)
or
=DateSerial( year(today()), month(today()), 1) 
Expression Output Example:11/1/2010 12:00:00 AM
Return first day of current year 
ex. Default Start Date parameter to return YTD)
Expression on the parameter default value: 
=DateAdd("d",-DatePart(DateInterval.DayOfYear,Today,0,0)+1,Today) 
Expression Output Example: 1/1/2010 12:00:00 AM
Return period over period 
(ex. Default date parameters to a rolling year)
Expression on the parameter default value: 

Week over Week 
=DateAdd("ww",-1, Today) 

Month over Month 
=DateAdd("m",-1,Today) 

Year over Year 
=DateAdd("yyyy",-1, Today) 

Expression Output Example:10/9/2010 12:00:00 AM
Return current month nameExpression in Text Box: 
=MonthName(Month(Today())) 

Expression Output Example:November
Uppercase fieldsExpression in Text Box: 
=UCASE(Fields!FieldName.Value) 

Expression Output Example:NOVEMBER
Convert text to proper case 
(ex. 1st letter in each word is uppercase)
Expression in Text Box: 
=StrConv(Fields!FieldName.Value, VbStrConv.ProperCase)
Replace NULL with another valueExpression in Text Box: 
=iif(Fields!FieldName.Value = nothing, "No Value",Fields! FieldName.Value)
Alternating row color (Banding effect)BackgroundColor property on Text Box: 
=iif(RowNumber(Nothing) Mod 2 = 0, "Silver", "White")
Handling division by zeroExpression in Text Box: 

=iif(Fields!DenominatorField.Value = 0, 0, Fields!NumeratorField.Value/ 

iif(Fields!DenominatorField.Value = 0, 1, Fields! DenominatorField.Value))
security number)Expression in Text Box: 

=Replace(Fields!EmailAddress.Value,"-","")

source : http://pragmaticworks.com/Training/Resources/Cheat-Sheets/SSRS-Expression-Cheat-Sheet

Show all records/some records based on parameter value

Method 1 
You need to set up a filter similar to the following:
enter image description here
Where the expression is:
=IIf(Parameters!FilterColumn.Value = Fields!Category.Value
        or Parameters!FilterColumn.Value = "All products"
    , "Include"
    , "Exclude")
This matches the row Category based on the parameter value, or, if the value = All products, will include all rows.
As mentioned in the comments and the other answer, this is possible in the SP too, but since it seems to be specifically to demonstrate the functionality this should do the trick at the report level.
--------------------------------------------------------------------------------------------------------------------------
Method 2 
I have created some solution and worked for me:
enter image description here
In Expression field, I put first expression:
1.  Iif(Parameters!FilterColumn.Value = "All", 1, Fields!Category.Value)
In Value field, I put second expression:
2.  Iif(Parameters!FilterColumn.Value = "All", 1, Parameters!FilterColumn.Value)
So, when I choose "All" value in parameter, then first expression will result 1, and second expression will result 1, and i have 1 = 1 which is true for all rows, and I got all rows in table.
When I choose specific category from parameter, then in first expression result will be Fields!Category.Value and in second expression will be Parameters!FilterColumn.Value. Simple, I got Fields!Category.Value = Parameters!FilterColumn.Value, or just give me rows where category is that choosen in parameter.
source : http://stackoverflow.com/questions/18203317/show-all-records-some-records-based-on-parameter-value



Tuesday, September 20, 2016

การเขียน Connection String แบบต่างๆ เพื่อเชื่อมต่อ SQLConnection (.Net)

การเขียน Connection String แบบต่างๆ เพื่อเชื่อมต่อ SQLConnection (.Net)

ผมมีความรู้สึกว่า แต่ละคน  มีการสร้างการติดต่อฐานข้อมูลต่างกันครับ
อาจจะเป็นเพราะว่า ยังไม่รู้  หรือ  รู้อยู่แบบเดียว  หรือ ยังไม่เข้าใจ หลักการเชื่อมต่อฐานข้อมูล
จึงเอามาเพื่อให้รู้เพิ่มอีกหน่อยครับ

ในการทำให้โปรแกรมของเรา สามารถติดต่อฐานข้อมูล
อันนึงที่มักเป็นปัญหา บ่อยๆ คือ การเขียน Connection String ผิด

ทำไมผิด ?บ่อยครั้งที่ผมเขียนผิด ก็นั่งงง เป็นวัน  ว่าทำไมคนอื่นทำแบบเดียวกันแล้ว connect ได้
แล้วเราทำไม่ได้   แล้วก็หลายครั้งนั้น   ผมก็หาสาเหตุได้ว่า เพราะสภาพแวดล้อม ไม่เหมือนกัน
ไม่ได้เกี่ยวว่า บ้านใครอยู่ที่ไหน  แต่เกี่ยวกับว่า  โปรแกรมของเรา ติดต่อไปยัง DB Server ที่เป็นแบบไหน
ต่างหาก  เช่น  
WindowsXP + SQL Server บนเครื่องเดียวกัน
WindowsXP เครื่องหนึ่ง  SQL Server อีกเครื่องหนึ่ง Windows 2000 Server
SQL Server มีมากกว่า 1 Instance หรือ ไม่ได้ใช้ชื่อ Default Stance
ต่างคนก็ต่างรูปแบบกันไป 
บางครั้งมี IIS เพื่อทำ Web Server มาอีก  เลยงงไปใหญ่

เรามาดูกันครับ ว่า แยกโดยง่ายๆแล้ว  เป็นยังไง
ตัวอย่างจะทำการติดต่อ SQL Server ดังนี้

* server01 คือชื่อเครื่องที่เป็น DB Server
   serverName\instanceName ในที่นี้ คือ server01\instance01
   กรณีที่ เราใช้ instance ห้ามลืมเด็ดขาดที่ต้องระบุ instance name ด้วยทุกครั้ง
   Initial Catalog คือ ชื่อ ฐานข้อมูล ให้ชื่อว่า StoreDB
   User Id และ Password  คือ login สำหรับ SQL Server เช่น sa [ไม่แนะนำให้ใช้]


แบบแรก เรียกว่า
Standard Security:
เขียนสองแบบ  อันไหนก็ได้ครับ ให้ผลเหมือนกัน
กรณีที่เราได้สร้าง User ไว้ใน SQL Server ไว้แล้ว  หรือ  ไปขอเขาใช้ SQL Server คนอื่น แล้วเขาให้ User กับ Password สำหรับ ติดต่อฐานข้อมูลเท่านั้น

myconn = "Data Source=server01;Initial Catalog=StoreDB;User Id=sa;Password=sapassword;"
หรือ
myconn = "Server=server01;Database=StoreDB;User ID=sa;Password=sapassword;Trusted_Connection=False"

   ส่วน Trusted_Connection=False เนี่ย ต้องระบุด้วยนะครับ เพราะเราจะขอใช้งาน User Id ของ SQL Server เลย

แบบสอง เรียกว่า
Trusted Connection:
อันนี้ พิเศษ สำหรับ Windows Server ครับ คือ SQL Server ที่ ติดตั้ง แบบ Mixed Mode คือ สามารถใช้ได้ทั้ง User Id บนระบบ Windows 2000 และ SQL Server login  เพื่อติดต่อฐานข้อมูล หรือว่าโปรแกรมทำงานบนเครื่องเดียวกันกับ SQL Server หรือ เครื่องสองเครื่อง ได้ Trusted กันเรียบร้อยแล้ว
myconn = "Data Source=server01;Initial Catalog=StoreDB;Integrated Security=SSPI;"
หรือ
myconn = "Server=server01;Database=StoreDB;Trusted_Connection=True;"

ทั้งสองแบบนี้ ก็ให้ผลแบบเดียวกัน แล้วแต่จะเลือกใช้ 
เห็นไหมครับว่า  User Id กับ Password ไม่ต้องใส่อีกแล้ว เพราะการติดต่อจะมีการ Authen โดย Windows เองอยู่แล้ว

แบบสุดท้าย
Connect via an IP address:
ติดต่อ SQL Server อีกเครื่องหนึ่ง ชื่อเครื่องก็ไม่รู้  โปรโตคอล Netbios ก็ไม่ได้ใช้  รู้อย่างเดียวคือ IP address ของ SQL Server (SQL Server เป็น service ที่ใช้ TCP Port 1433 เป็น Default Port เปลี่ยนเป็นอันอื่น ถ้าไม่ได้ใช้ Port นี้)
myconn = "Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog=StoreDB;User ID=sa;Password=sapassword;"

* Network Library เพื่อเลือกค่าที่ต้องใช้ให้ถูกตัว ต้องรู้เพิ่มนิดหนึ่งครับว่า ต้องติดต่อแบบไหน แต่โดยทั่วไป เป็น Win32 Winsock TCP/IP อยู่แล้ว ถ้าไม่รู้ใส่ อันนี้ไปก่อน

แบบต่างๆ ของ  Network library
Name           Network library
dbnmpntw     Win32 Named Pipes
dbmssocn     Win32 Winsock TCP/IP
dbmsspxn     Win32 SPX/IPX
dbmsvinn     Win32 Banyan Vines
dbmsrpcn     Win32 Multi-Protocol (Windows RPC)



หมดแล้วล่ะครับ ทั่วไปก็ใช้อยู่เท่านี้ ดูแล้วไม่ยากเลยใช่ไหม
ทีนี้มาดูว่าใช้ยังไง

สำหรับ C#:
using System.Data.SqlClient;

SqlConnection mySQLConn = new SqlConnection();
mySQLConn.ConnectionString = myconn;
mySQLConn.Open();

สำหรับ VB.NET:
Imports System.Data.SqlClient

Dim mySQLConn As SqlConnection = New SqlConnection()
mySQLConn.ConnectionString = myconn
mySQLConn.Open()

จะเลือกใช้อย่างไหนก็เลือกดูเอานะครับ ว่า สภาพแวดล้อม ของเราเป็นแบบไหน

Source : http://greatfriends.biz/webboards/msg.asp?id=7391

Tuesday, January 26, 2016

Rolling up multiple rows into a single row and column for SQL Server data

Problem
I need a way to roll-up multiple rows into one row and one column.  I know I can roll-up multiple rows into one row using Pivot, but I need all of the data concatenated into a single column in a single row. In this tip we look at a simple approach to accomplish this.
Solution
To illustrate what is needed, here is a sample of data in a table:
Users per sector sales
This is one example of what we want the end result to look like:
sample output
The solution proposed in this tip explores two SQL Server commands that can help us achieve the expected results.  The commands to be used are STUFF and FOR XML.

Preparing Sample Data

Before we begin, we'll create some tables and sample data which the following script will do for us.
CREATE TABLE SALES_SECTORS(
SEC_ID INT,
SEC_NAME VARCHAR(30))
GO
CREATE TABLE USRS(
USR_ID INT,
USR_NAME VARCHAR(30),
SEC_ID INT
)
GO
CREATE TABLE ADV_CAMPAIGN(
ADV_ID INT,
ADV_NAME VARCHAR(30)
)
GO
CREATE TABLE USR_ADV_CAMPAIGN(
USR_ID INT,
ADV_ID INT
)
GO
CREATE TABLE SEC_ADV_CAMPAIGN(
SEC_ID INT,
ADV_ID INT
)
GO
INSERT INTO SALES_SECTORS( SEC_ID, SEC_NAME ) VALUES ( 1, 'ENTERTAINMENT' )
INSERT INTO SALES_SECTORS( SEC_ID, SEC_NAME ) VALUES ( 2, 'CLOTHES' )
GO
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 1, 'ANDERSON', 1 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 2, 'CHARLES', 1 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 3, 'DANNY', 1 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 4, 'LUCAS', 1 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 5, 'KEITH', 2 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 6, 'STEFAN', 2 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 7, 'EDUARD', 2 )
INSERT INTO USRS( USR_ID, USR_NAME, SEC_ID ) VALUES ( 8, 'BRAD', 2 )
GO
INSERT INTO ADV_CAMPAIGN( ADV_ID, ADV_NAME ) VALUES ( 1, 'SONY ENTERTAINMENT' )
INSERT INTO ADV_CAMPAIGN( ADV_ID, ADV_NAME ) VALUES ( 2, 'BEATS SOUNDS' )
INSERT INTO ADV_CAMPAIGN( ADV_ID, ADV_NAME ) VALUES ( 3, 'BOOSE' )
INSERT INTO ADV_CAMPAIGN( ADV_ID, ADV_NAME ) VALUES ( 4, 'POLO RALPH LAUREN' )
INSERT INTO ADV_CAMPAIGN( ADV_ID, ADV_NAME ) VALUES ( 5, 'LACOSTE' )
GO
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 1, 1 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 1, 2 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 2, 2 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 2, 3 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 3, 3 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 4, 2 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 5, 4 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 6, 5 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 7, 4 )
INSERT INTO USR_ADV_CAMPAIGN( USR_ID, ADV_ID ) VALUES ( 8, 5 )
GO
INSERT INTO SEC_ADV_CAMPAIGN( SEC_ID, ADV_ID ) VALUES ( 1, 1 )
INSERT INTO SEC_ADV_CAMPAIGN( SEC_ID, ADV_ID ) VALUES ( 1, 2 )
INSERT INTO SEC_ADV_CAMPAIGN( SEC_ID, ADV_ID ) VALUES ( 1, 3 )
INSERT INTO SEC_ADV_CAMPAIGN( SEC_ID, ADV_ID ) VALUES ( 2, 4 )
INSERT INTO SEC_ADV_CAMPAIGN( SEC_ID, ADV_ID ) VALUES ( 2, 5 )
GO

STUFF() Function

Before going to the examples, we need to understand the workings of the commands mentioned above. The STUFF() function puts a string in another string, from an initial position.  With this we can insert, replace or remove one or more characters.
This syntax is STUFF(character_expression, start, length, replaceWith_expression):
  • character_expression: string to be manipulated
  • start: initial position to start
  • length: number of characters to be manipulated
  • replaceWith_expression: characters to be used
Here is an example of the how to use the STUFF command. 
For our example we have a string that looks like this:
;KEITH;STEFAN;EDUARD;BRAD
We want to remove the first ; from the list so we end up with this output:
KEITH;STEFAN;EDUARD;BRAD
To do this we can use the STUFF command as follows to replace the first ; in the string with an empty string.
SELECT STUFF(';KEITH;STEFAN;EDUARD;BRAD', 1, 1, '')
And this returns this output:
KEITH;STEFAN;EDUARD;BRAD

FOR XML Clause

The FOR XML clause, will return the results of a SQL query as XML. The FOR XML has four modes which are RAW, AUTO, EXPLICIT or PATH.  We will use the PATH option, which generates single elements for each row returned.
If we use a regular query such as the following it will return the result set shown below.
SELECT 
   SS.SEC_NAME, 
   US.USR_NAME
FROM SALES_SECTORS SS
INNER JOIN USRS US ON US.SEC_ID = SS.SEC_ID
ORDER BY 1, 2

Users per sector sales
If we take this a step further, we can use the FOR XML PATH option to return the results as an XML string which will put all of the data into one row and one column.
SELECT 
   SS.SEC_NAME, 
   US.USR_NAME 
FROM SALES_SECTORS SS 
INNER JOIN USRS US ON US.SEC_ID = SS.SEC_ID 
ORDER BY 1, 2 
FOR XML PATH('')

Putting It All Together

Example 1

Now that we see what each of these commands does we can put these together to get our final result.
The example query below uses a subquery where we are returning XML data for the USR_NAME from table USRS and joining this to the outer query by SEC_ID from table SALES_SECTORS.  For each value from the inner query we are concatenating a ";" and then the actual value to have all of the data from all rows concatenated into one column.  We are grouping by SEC_NAME to show all USERS within that SECTOR. 
SELECT 
   SS.SEC_NAME, 
   (SELECT '; ' + US.USR_NAME 
    FROM USRS US
    WHERE US.SEC_ID = SS.SEC_ID
    FOR XML PATH('')) [SECTORS/USERS]
FROM SALES_SECTORS SS
GROUP BY SS.SEC_ID, SS.SEC_NAME
ORDER BY 1
The below is the output for this query.  We can see that we have the leading ; in the SECTORS/USERS column which we don't want.
In this modified example, we are now using the STUFF function to remove the leading ; in the string.
SELECT 
   SS.SEC_NAME,
   STUFF((SELECT '; ' + US.USR_NAME 
          FROM USRS US
          WHERE US.SEC_ID = SS.SEC_ID
          FOR XML PATH('')), 1, 1, '') [SECTORS/USERS]
FROM SALES_SECTORS SS
GROUP BY SS.SEC_ID, SS.SEC_NAME
ORDER BY 1
And we get this resultset:
If we also want to order the SECTORS/USERS data we can modify the query as follows:
SELECT 
   SS.SEC_NAME,
   STUFF((SELECT '; ' + US.USR_NAME 
          FROM USRS US
          WHERE US.SEC_ID = SS.SEC_ID
          ORDER BY USR_NAME
          FOR XML PATH('')), 1, 1, '') [SECTORS/USERS]
FROM SALES_SECTORS SS
GROUP BY SS.SEC_ID, SS.SEC_NAME
ORDER BY 1

Example 2

If we want this all to be in one column we can change the query a little as follows:
SELECT 
   SS.SEC_NAME + ': ' +
   STUFF((SELECT '; ' + US.USR_NAME 
          FROM USRS US
          WHERE US.SEC_ID = SS.SEC_ID
          FOR XML PATH('')), 1, 1, '') [SECTORS/USERS]
FROM SALES_SECTORS SS
GROUP BY SS.SEC_ID, SS.SEC_NAME
ORDER BY 1
And this gives us this result:
Users concatenated by sale sectors

Example 3

This example takes it a step further where we have multiple subqueries to give us data based on USERS within CAMPAIGNS within SECTORS.
SELECT 
    SS.SEC_ID, 
    SS.SEC_NAME,
    STUFF((SELECT '; ' + AC.ADV_NAME + ' (' + 
             STUFF((SELECT ',' + US.USR_NAME
                    FROM USR_ADV_CAMPAIGN UAC
                    INNER JOIN USRS US 
                          ON US.USR_ID = UAC.USR_ID
                    WHERE UAC.ADV_ID = SAC.ADV_ID
                    FOR XML PATH('')), 1, 1, '') + ')'
           FROM ADV_CAMPAIGN AC
           INNER JOIN SEC_ADV_CAMPAIGN SAC 
                 ON SAC.ADV_ID = AC.ADV_ID AND SAC.SEC_ID = SS.SEC_ID 
           ORDER BY AC.ADV_NAME
           FOR XML PATH('')), 1, 1, '') [CAMPAIGNS/USERS PER SECTOR]
FROM SALES_SECTORS SS
GROUP BY 
     SS.SEC_ID, 
     SS.SEC_NAME

Users/Campaigns concatenated by sale sectors

Conclusion

There are always several options to complete a task within SQL Server and we should take the time to explore the capabilities offered by the database before developing large and complex code. I hope this is one more of those examples that shows there are sometimes easier approaches than you think might be available.
Next Steps
  • Take this further and create simple queries and then deepen the complexity of the code.
  • Explore the commands used in this tip further to see what other things you might be able to do.
  • Some more details about the commands used above can be obtained from MSDN using the links below:


Last Update:  

Source : https://www.mssqltips.com/sqlservertip/2914/rolling-up-multiple-rows-into-a-single-row-and-column-for-sql-server-data/