Create view with JSON array based on many to many table - sql

I have a typical table with users. I have also a many to many table where first column is UserId and second BusinessId. I want to create a view with users where their businessId will be as json.
I tried something like this:
SELECT
ISNULL(CAST(u.[Id] AS INT), 0) AS [Id]
,(SELECT BusinessId FROM [TableA].[dbo].[user_business_entities] WHERE UserId = u.Id FOR JSON AUTO) AS BusinessEntityIds
FROM
[TableA].[dbo].[core_users] u
But in view I get this:
Id
BusinessEntityIds
1
[{"BusinessId":1925},{"BusinessId":1926}]
2
[{"BusinessId":15}]
It's pretty good, but it would be best if json had only values, no key name i.e only ids without "BusinessId":
Id
BusinessEntityIds
1
[1925, 1926]
2
[15]
How can I do this?

Two quick options: First is for <=2016 and the 2nd is 2017+
Never understood why MS never provided this functionality of a simple ARRAY.
Option 1 <=2016
Select ID
,BusinessEntityIds = '['+stuff((Select concat(',',BusinessEntityIds)
From YourTable
Where ID=A.ID
For XML Path ('')),1,1,'')+']'
From YourTable A
Group By ID
Option 2 2017+
select ID,
BusinessEntityIds = '['+string_agg(BusinessEntityIds, ',') +']'
from YourTable
group by ID
Both Results Are
ID BusinessEntityIds
1 [1925,1926]
2 [15]

Related

Building a string based on columns from a GROUP

I have a table like this:
user 1 A
user 1 B
user 2 H
user 2 G
user 2 A
and I need a result like:
user 1 AB
user 2 HGA
Is there a way to obtain a result like this?
So here we create some test data
CREATE TABLE foo AS
SELECT * FROM (
VALUES (1,'A'),(1,'B'),(2,'H'),(2,'G'),(2,'A')
) AS f(id,col);
This should work,
SELECT id, array_to_string(array_agg(col), '')
FROM table
GROUP BY id;
Here is what we're doing,
GROUP BY id.
Build a PostgreSQL text[] (text array) of that column with array_agg
Convert the array back to text by joining on an empty string '' with array_to_string.
You can also use string_agg,
SELECT id, string_agg(col, '')
FROM foo
GROUP BY id;
The better soluction is using str_sum agregate function
select
user,
str_sum(column_name,'')
from table_name
group by user;

How Make a Hierarchical Selection with SQL Query

I have a problem in creating a SQL Query as follows :
I Have 2 Tables with following Specification and data:
http://dc699.4shared.com/img/lgtP3N_4ce/s3/144c7252ff8/SQL1.jpg
I want to create a SQL Select Query to return for me a Hierarchical Model Like this :
For example if the SID is 3 it should return for me this :
http://dc699.4shared.com/img/8UufpK2-ce/s3/144c7255af0/SQL2.jpg
Because the Num 3 in structure table related to data 7,8,9 and 9 is related to 10,11(Note that No 9 is related to 3 or in other words 9 is subset of 3)
Can anyone help me to create this Query? I have try for 2 weeks but I failed :(
Thanks so much
You can also try an Rank solution like this one
WITH Personel_Structure AS
(
SELECT [SID],MID, RANK() OVER(PARTITION BY [SID] ORDER BY MID ASC) AS POS
FROM Structure
WHERE [SID] = 3
)
SELECT [SID],MID
FROM Personel_Structure
ORDER BY POS ASC
I have script this against the structure table if you need to do a join to the personel table that should be easy from here. Just join the the tables in the CTE.
Untested answer, and it does not include the root member for readability and because your examples in the question and comments are inconsistent. This should get you going.
I made the query starting with root = 1
WITH members (id)
AS
(SELECT MID as id FROM structure WHERE SID = 1
UNION ALL
SELECT MID as id
FROM members
INNER JOIN structure ON (members.id = structure.SID)
)
SELECT members.ID FROM members;
members is the intermediary table created by the CTE (WITH...)
sqlfiddle

How to iterate through an SQL table which "parent" and child" rows are in same table

In a table there are the columns ID, Title and ParentID. ParentID is used for the ID of the entry in the same table which is considered its parent - thus any entry in which ParentID is NULL is one which is itself a parent.
I need a query which will iterate through each parent and list any child below it (ideally with a hyphen or something to denote its subordination) does anyone know how this can be done or how to point me in the right direction?
(I've looked into T-SQL and read many similar online questions however my SQL isn't quite sharp enough to make sense of it, so I'd greatly appreciate some pointers!)
Here you are!
WITH n(ID, Title) AS
(SELECT ID, Title
FROM YourTable
WHERE ID = (SELECT TOP 1 ID FROM YourTable WHERE ParentID IS NULL)
UNION ALL
SELECT nplus1.ID, nplus1.Title
FROM YourTable as nplus1, n
WHERE n.ID = nplus1.ParentID)
SELECT ID, Title FROM n
To get hierarchy data from self-referencing table, you can use WITH syntax in sql 2008
WITH n(ID) AS
(SELECT ID FROM YourTable
UNION ALL
SELECT nplus1.ID
FROM YourTable as nplus1, n
WHERE n.ID = nplus1.ParentID)
SELECT ID FROM n

How can I join these two tables into the same Sql result

I'm trying to generate a SQL query that can join two tables together and return the result .. but the second table is 'flattened'. I'm not sure if that's the correct technical term. Is it denormalized?
Anyways, can someone suggest how I could do this?
Table: Users
UserId Name
1 Pure.Krome
2 John
3 Jill
4 Jane
Table: UserAliases
UserAliasId UserId Alias
1 1 Idiot
2 1 PewPew
3 3 BlahBlahBlah
Desired results
UserId Name Aliases
1 Pure.Krome Idiot PewPew
2 John
3 Jill BlahBlahBlah
4 Jane
Please note:
A user does NOT need to have an alias. So that's a zero->many relationship (outer join)
The delimiter for the flattening of the 2nd table is a SPACE. If an alias has a space, bad luck for me. (Consider it, bad data).
Another example of my problem is to think of a StackOverflow question + tags.
http://groupconcat.codeplex.com/ has a clone of MySQL's GROUP_CONCAT() implemented as a CLR aggregation function. I guess the SQL is not the problem, but I might as well:
SELECT
[Users].[UserId] AS UserId,
[Users].[Name] AS Name,
GROUP_CONCAT_D([UserAliases].[Alias]," ") AS Aliases
FROM [Users]
OUTER JOIN [UserAliases] ON [Users].[UserId]=[UserAliases].[UserId]
or similar.
This is not tested but give it a try. I have no server here.
SELECT a.UserID,
a.[Name],
coalesce(NewTable.NameValues, '') Aliases
FROM Users a LEFT JOIN
(
SELECT UserID,
STUFF((
SELECT ' ' + [Name]
FROM UserAliases
WHERE ( UserID = Results.UserID )
FOR XML PATH('')), 1, 2, '') AS NameValues
FROM UserAliases Results
GROUP BY UserID
) NewTable
on a.UserID = NewTable.UserID
Here's SQL Fiddle Output
FOR XML PATH is handy in this situation:
SELECT UserID, Name
, LTRIM(RTRIM((SELECT ' ' + Alias
FROM UserAliases WHERE UserID = u.UserID
FOR XML PATH('')))) AS Aliases
FROM Users u

SQL PIVOT TABLE

I have the following data:
ID Data
1 tera
1 add
1 alkd
2 adf
2 add
3 wer
4 minus
4 add
4 ten
I am trying to use a pivot table to push the rows into 1 row with multiple columns per ID.
So as follows:
ID Custom1 Custom2 Custom3 Custom4..........
1 tera add alkd
2 adf add
3 wer
4 minus add ten
I have the following query so far:
INSERT INTO #SpeciInfo
(ID, [Custom1], [Custom2], [Custom3], [Custom4], [Custom5],[Custom6],[Custom7],[Custom8],[Custom9],[Custom10],[Custom11],[Custom12],[Custom13],[Custom14],[Custom15],[Custom16])
SELECT
ID,
[Custom1],
[Custom2],
[Custom3],
[Custom4],
[Custom5],
[Custom6],
[Custom7],
[Custom8],
[Custom9],
[Custom10],
[Custom11],
[Custom12],
[Custom13],
[Custom14],
[Custom15],
[Custom16]
FROM SpeciInfo) p
PIVOT
(
(
[Custom1],
[Custom2],
[Custom3],
[Custom4],
[Custom5],
[Custom6],
[Custom7],
[Custom8],
[Custom9],
[Custom10],
[Custom11],
[Custom12],
[Custom13],
[Custom14],
[Custom15],
[Custom16]
)
) AS pvt
ORDER BY ID;
I need the 16 fields, but I am not exactly sure what I do in the From clause or if I'm even doing that correctly?
Thanks
If what you seek is to dynamically build the columns, that is often called a dynamic crosstab and cannot be done in T-SQL without resorting to dynamic SQL (building the string of the query) which is not recommended. Instead, you should build that query in your middle tier or reporting application.
If you simply want a static solution, an alternative to using PIVOT of what you seek might look something like so in SQL Server 2005 or later:
With NumberedItems As
(
Select Id, Data
, Row_Number() Over( Partition By Id Order By Data ) As ColNum
From SpeciInfo
)
Select Id
, Min( Case When Num = 1 Then Data End ) As Custom1
, Min( Case When Num = 2 Then Data End ) As Custom2
, Min( Case When Num = 3 Then Data End ) As Custom3
, Min( Case When Num = 4 Then Data End ) As Custom4
...
From NumberedItems
Group By Id
One serious problem in your original data is that there is no indicator of sequence and thus there is no means for the system to know which item for a given ID should appear in the Custom1 column as opposed to the Custom2 column. In my query above, I arbitrarily ordered by name.