Aggregate/concatenate values from a column into a single row - sql-server

I have a couple thousand franchises, and about 3 or 4 service groups. The service groups are in a separate table, then i have third table joining them together. A franchise may be connected to 1 or many service groups. What I am trying to achieve is listing out the franchises, with a column labeled "Service Categories". It would then be a comma separated list of which services they provide. So right now, here's my output:
id Service Groups name email address City State
1 Cleaning Services Franchise of LocationX example#example.com 123 Fake st. Springfield TheOneTheSimpsonsLiveIn
2 Disaster Services Franchise of LocationX example#example.com 123 Fake st. Springfield TheOneTheSimpsonsLiveIn
I would like to have it so it becomes this:
id Service Groups name email address City State
1 Cleaning Services, Disaster Services Franchise of LocationX example#example.com 123 Fake st. Springfield TheOneTheSimpsonsLiveIn
Any suggestions or references of methods/functions I can use to do this would be greately appreciated. Thanks!

try this
Declare #TempServiceGroups varchar(max)=''
Select COALESCE(#TempServiceGroups,'')+ServiceGroups+',' from MyTable
Select #TempServiceGroups AS ServiceGroups , Name,Email,Address,City,State
from MyTable

Related

Power BI Table Relationship

I am trying to create two relationships between tables in Power BI. I have a table (Observations) that contains an employee_id and a supervisor_id that I am trying to connect to my Contact table.
I need to look up the employee information in the Contact table by using employee_id in the Observation table and also look up the supervisor information in the Contact table using the supervisor_id in the Observation table.
Contact Table Observation Table
=================== =================
Employee_ID Name Position Observation_ID Employee_ID Supervisor_ID
--------------------------------------- ----------------------------------------------
123 John Doe employee 1 123 321
321 Harvey Sample supervisor 2 456 654
456 Mickey Mouse employee 3 456 654
654 Donald Duck supervisor 4 123 321
One possible way is to create two relationships between the observation and contact table:
Create a relationship between Observation Table(Employee_ID) and Contact Table(Employee_ID). The Cardinality should be many to one, and set this relationship as active.
Create a relationship between Observation Table(Supervisor_ID) and Contact Table(Employee_ID). The Cardinality should be many to one, and set this relationship as inactive.
create an inactive relationship Power BI
You will then need to use the DAX USERELATIONSHIP function when you want to use the inactive relationship in a formula. Here is a detailed explanation of how to use USERELATIONSHIP: https://www.sqlbi.com/articles/userelationship-in-calculated-columns/
Alternatively, you can duplicate the contact table and use one copy for the Employee_ID relationship and the other for the Supervisor_ID relationship. Which option is best will depend on your use case.

How can I build a query to view the same value in 20 or more tables in SQL?

Scenarios:
Table 1
Name ID dept
John 112 Fin
Mary 113 Act
Table 2
Name email
John John#gmail.com
Mary Max#gmail.com
Table 3
Name Supervisor
John Kelly
Mary Adam
Table 4
Namevalue Salary
John 1000
Mary 1000
Expected Output:
I would like to know the occurrence of John and Mary in all these tables. There are more than 20 tables in difference database.
Firstly, specify the master table according to data quality, use this table as base and then use left joins to concat with other tables.
But, I think, there is a design problem in the database so maybe creating keys for each user can be useful.
For example, name + surname + User Something to make records unique then use joins otherwise all records will duplicate.

I want To select Particular sentence from column using Like for creating view can anyone help me on this ,

#NEG MR Neg–Pending: Oliver to arrange cutting of management keys and keys for tenants
#NEG MR Neg– Pending: Oliver to ensure the tenant has inspected the property before the move in date of 05/11/2014
#NEG MR Neg– Pending: Oliver to email copy of key release form and photocopy of keys held by mr…. This will be done Monday 27th Oct as well as references etc.
this is My column data and i want to get result of only from #NEG to next # sign that is
Result should look Like this
#NEG MR Neg–Pending: Oliver to arrange cutting of management keys and keys for tenants
Assuming I'm understanding what you need correctly... try this...
SELECT
SUBSTRING(YourColumn,CHARINDEX('#NEG',YourColumn,0),
CHARINDEX('#NEG',YourColumn,4)-1)
FROM YourTable
... select Replace(REPLACE(test,'$',''),'Mr Neg','')as test,
Replace(REPLACE(test2,'$',''),'Mr Neg','')as test2,
Replace(REPLACE(test3,'$',''),'Mr Neg','')as test3
--REPLACE(test2,'$','')as test2,REPLACE(test3,'$','')as test3
From (
select substring(a.test,1,charindex('$',a.test,1))as test,substring(a.test2,1,charindex('$',a.test2,1))as test2
,substring(a.test3,1,charindex('$',a.test3,1))as test3
from (SELECT replace(convert(varchar(150),SUBSTRING(name,CHARINDEX('#NEG1',name,5), CHARINDEX('$',name,7)+70) ),'#NEG1','')as test,
replace(convert(varchar(150),SUBSTRING(name,CHARINDEX('#NEG2',name,5), CHARINDEX('$',name,7)+70) ),'#NEG2','')as test2,
replace(convert(varchar(150),SUBSTRING(name,CHARINDEX('#NEG3',name,5), CHARINDEX('$',name,7)+70) ),'#NEG3','')as test3
,name
FROM test3nov2014 where name like '%#neg%')as a
)b

SQL Server 2008 View Group By

I have created the following view in SQL Server 2008 to create mailing lists for land owners:
SELECT
dbo.parcel.featid,
CAST(mms_db.dbo.TR_Roll_Master.FMT_ROLL_NO AS decimal(11, 3)) AS Roll,
dbo.parcel.survey, mms_db.dbo.Central_Name_Database.NAME AS Owner,
mms_db.dbo.Central_Name_Database.NAME_2 AS Owner2,
mms_db.dbo.Central_Name_Database.BOX_NUM,
mms_db.dbo.Central_Name_Database.APT_NUM,
mms_db.dbo.Central_Name_Database.FMT_STREET AS House_num,
mms_db.dbo.Central_Name_Database.CITY AS Town,
mms_db.dbo.Central_Name_Database.PROV_CD AS Prov,
mms_db.dbo.Central_Name_Database.POST_CD AS Post_code,
mms_db.dbo.TR_Roll_Number_Owners.NAME_CODE
FROM
mms_db.dbo.TR_Roll_Master
INNER JOIN
dbo.parcel ON mms_db.dbo.TR_Roll_Master.ROLL_NO = dbo.parcel.roll_no COLLATE SQL_Latin1_General_CP1_CI_AS
INNER JOIN
mms_db.dbo.TR_Roll_Number_Owners ON mms_db.dbo.TR_Roll_Master.ROLL_NO = mms_db.dbo.TR_Roll_Number_Owners.ROLL_NO
INNER JOIN
mms_db.dbo.Central_Name_Database ON mms_db.dbo.TR_Roll_Number_Owners.NAME_CODE = mms_db.dbo.Central_Name_Database.NAME_CODE
WHERE
(mms_db.dbo.TR_Roll_Master.DEL_ROLL NOT LIKE '%Y%') AND
(mms_db.dbo.TR_Roll_Master.ROLL_NO NOT LIKE 'P%') OR
(mms_db.dbo.TR_Roll_Master.DEL_ROLL IS NULL) AND (mms_db.dbo.TR_Roll_Master.ROLL_NO NOT LIKE 'P%') OR
(mms_db.dbo.TR_Roll_Master.DEL_ROLL NOT LIKE '%I%') AND
(mms_db.dbo.TR_Roll_Master.ROLL_NO NOT LIKE 'P%')
The view works fine however there are often duplicates as many people own more than one piece of land. I would like to group by Name_Code to eliminate the duplicates.
When I add:
Group by mms_db.dbo.TR_Roll_Number_Owners.NAME_CODE
to the end of the query I am returned with the following response:
SQL Execution Error.
Executed SQL statement: SELECT dbo.parcel.featid, CAST(mms_db.dbo.TR_Roll_Master.FMT_ROLL_NO AS decimal(11,3)) AS Roll,
dbo.parcel.survey,
mms_db.dbo.Central_NameDatabase.Name AS Owner,
mms_db.dbo.Central_Name_Database.NAME_2 AS Owner2,
mms_db.dbo.Central_Name_Database.B...
Error Source: .Net SQLClient Data Provider
Error Message: Column 'dbo.parcel.featid' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
I'm not sure what I need to change to make this work.
--Edit--
As a sample data, here is a condensed sample of what I would like to achieve
Roll Owner Box_Num Town Prov Post_code Name_Code
100 John Smith 50 Somewhere MB R3W 9T7 00478
200 John Smith 50 Somewhere MB R3W 9T7 00478
300 Peter Smith 72 Somewhere MB R3W 9T9 00592
400 John Smith 90 OtherPlace MB R2R 8V7 00682
John Smith has the name code of 00478. He owns both Roll 100 & 200, Peter Smith owns 300 and another person with the name of John Smith owns 400. Based on different Name_Code values I know that the two John Smith's are different people. I would like an output that would list John Smith with Name_Code 00478 1 time only while also listing Peter Smith and the other John Smith. Name_Code is the only value I can use for grouping as the rest could represent different people with the same name.
If you just want to eliminate duplicates, just use DISTINCT and exclude the columns representing other "people on more than one piece of land" from your query viz:
SELECT DISTINCT
NAME_CODE,
{column2},
{column3},
FROM
[MyView]
However, if you wish to perform aggregation of some sort, or show one random of the "people on more than one piece of land" then you will need the GROUP BY. All non-aggregated columns in the select need to appear in the group by:
SELECT
NAME_CODE,
... Other non aggregated fields here
COUNT(featid) AS NumFeatIds,
MIN(Owner2) AS FirstOwner,
... etc (other aggregated columns)
GROUP BY
NAME_CODE,
... All non-aggregated columns in the select.
Edit
To get the table listed in your edit, you would just need to ORDER BY Name_Code
However to get just one row of John Smith #00478, you need to compromise on the non-unique columns by either eliminating them entirely, using GROUP BY and aggregates on the rows, doing a GROUP_CONCAT type hack to e.g. comma separate them, or to pivot the duplicate row columns as extra columns on the one row.
Since you've mentioned GROUP repeatedly, it seems the aggregation route is necessary. John Smith #00478 has 2 properties, hence 2 discrete Roll values. So Roll can't appear in the aggregated result. So instead, you can return e.g. a count of the Rolls, or the MIN or MAX Roll, but not both Rows*. The other columns (Address related) are probably constant for all properties (assuming John Smith 00478 has one address), but unfortunately SqlServer will require you to include them in the GROUP.
I would suggest you try:
SELECT
COUNT(Roll) AS NumPropertiesOwned,
Owner,
Box_Num,
Town,
Prov,
Post_code,
Name_Code
FROM [MyNewView]
GROUP BY
Owner, Box_Num, Town, Prov, Post_code, Name_Code
ORDER BY Name_Code;
i.e. all the non-aggregated columns must be repeated in the GROUP BY
* unless you use the GROUP_CONCAT hack or the pivot route
its telling you what to do:
"Error Message: Column 'dbo.parcel.featid' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause."
This means you have to group the other (non-aggregated) fields too.

SQL Server Case Subquery

I have a database table that records staff contacts with clients. Usually only 1 staff member contacts a client, however occasionally 2 staff members have a contact with a client at the same time. One staff member is flagged as the primary, the other the secondary. To provide a link the one flagged as secondary will have the ContactID of the primary stored in the SecondaryContactID field, like in this example:
ContactID SecondaryContactID ContactDate StaffMemberID ContactLocation
--------- ------------------ ----------- ------------- ---------------
123456 Null 01/JUL/2013 John SydneyCBD
123457 123456 01/JUL/2013 James Null
Our major corporate app has a bug in that it does not store the same ContactLocation for the secondary staff member as the primary (even though they are always the same location in reality), its defaulting to Null. So in the example above "SydneyCBD" should be in both rows.
In my extract I need these records on 2 rows pretty much like the example, but how do I get SydneyCBD to print instead of Null...some sort of case subquery using the SecondaryContactID as a link?
You can try something like this:
SELECT T1.CONTACTID,
SECONDARYCONTACTID,
CONTACTDATE,
STAFFMEMBERID,
ISNULL(T1.CONTACTLOCATION, T2.CONTACTLOCATION) ContactLocation
FROM TABLE1 T1
LEFT JOIN (SELECT CONTACTLOCATION,
CONTACTID
FROM TABLE1)T2
ON T1.SECONDARYCONTACTID = T2.CONTACTID
A working example can be found on SQL Fiddle.

Resources