Hierarchical data with CTE - sql

I am sorry if the answer has been posted already, but I was not able to find the answer even after searching.
I have the following table
CREATE TABLE [dbo].[emp](
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
) ON [PRIMARY]
With data
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (1, N'a', 0)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (2, N'a1', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (3, N'a11', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (4, N'a12', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (5, N'a13', 2)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (6, N'a2', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (7, N'a3', 1)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (8, N'a31', 7)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (9, N'a32', 7)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (10, N'b', 0)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (11, N'b1', 10)
INSERT [dbo].[emp] ([id], [name], [mgrid]) VALUES (12, N'b2', 10)
And I would like the following output
a
a1
a11
a12
a13
a2
a3
a31
a32
b
b1
b2
Is this possible in SQL Server?

SQLFiddle demo
You can use ' ' instead of '+' in the last line to pad a string.
with t as
(
select id,name,mgrid,1 as level,cast(name as varchar(max)) as path
from emp where mgrid=0
union all
select emp.id,emp.name,emp.mgrid, t.level+1 as level,
t.path+cast(emp.name as varchar(max)) as path
from emp
join t on emp.mgrid=t.id
)
select replicate('+', level)+name from t order by path

with CTE as
(
select *
, level = 1
from emp
where mgrid = 0
union all
select emp.id,
name = cast(space((level) * 3) + emp.name as varchar(20)),
emp.mgrid,
level = level + 1
from emp
inner join CTE on CTE.id = emp.mgrid
)
select name
from CTE
order by ltrim(name)

Query:
DECLARE #temp TABLE
(
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
)
INSERT INTO #temp ([id], [name], [mgrid])
VALUES
(1, N'a', 0), (2, N'a1', 1),
(3, N'a11', 2), (4, N'a12', 2),
(5, N'a13', 2), (6, N'a2', 1),
(7, N'a3', 1), (8, N'a31', 7),
(9, N'a32', 7), (10, N'b', 0),
(11, N'b1', 10), (12, N'b2', 10)
DECLARE #out VARCHAR(MAX) = ''
;WITH cte AS
(
SELECT *, Lvl = 0, nn = CAST(name AS VARCHAR(MAX))
FROM #temp
WHERE mgrid = 0
UNION ALL
SELECT t.*, c.Lvl + 1, nn = CAST(REPLICATE(' ', c.Lvl + 1) + t.name AS VARCHAR(MAX))
FROM #temp t
JOIN cte c ON c.id = t.mgrid
)
SELECT #out = (
SELECT nn + CHAR(13)
FROM cte
ORDER BY LTRIM(nn)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #out
Output:
a
a1
a11
a12
a13
a2
a3
a31
a32
b
b1
b2

You can use CTE (Comnon table expression to achieve this)
check this sample code:
declare #emp table(
[id] [int] NOT NULL,
[name] [varchar](20) NULL,
[mgrid] [int] NULL
)
INSERT #emp ([id], [name], [mgrid]) VALUES (1, N'a', 0)
INSERT #emp ([id], [name], [mgrid]) VALUES (2, N'a1', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (3, N'a11', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (4, N'a12', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (5, N'a13', 2)
INSERT #emp ([id], [name], [mgrid]) VALUES (6, N'a2', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (7, N'a3', 1)
INSERT #emp ([id], [name], [mgrid]) VALUES (8, N'a31', 7)
INSERT #emp ([id], [name], [mgrid]) VALUES (9, N'a32', 7)
INSERT #emp ([id], [name], [mgrid]) VALUES (10, N'b', 0)
INSERT #emp ([id], [name], [mgrid]) VALUES (11, N'b1', 10)
INSERT #emp ([id], [name], [mgrid]) VALUES (12, N'b2', 10);
with cte (id,name, MGRID) as
(
select id, name,MGRID
from #emp
union all
select c.id, c.name, c.MGRID
from #emp c
inner join cte p
on c.mgrid = P.id
)
SELECT Distinct * FROM CTE

WITH RCTE AS
(
SELECT id, name, mgrid, CAST('' AS NVARCHAR(MAX)) AS blanks , CAST(name AS NVARCHAR(MAX)) AS ordr
FROM dbo.emp WHERE mgrid = 0
UNION ALL
SELECT e.id, e.name, e.mgrid, blanks + ' ' AS blanks, ordr + e.name AS ordr
FROM dbo.emp e
INNER JOIN RCTE r ON e.mgrid = r.id
)
SELECT blanks + name FROM RCTE
ORDER BY ordr

Related

How to convert rows to columns with commasepart using huge data in SQL Server

I have a question about SQL Server: how to convert rows to columns with comma-separated data using bulk data?
CREATE TABLE [dbo].[Emp]
(
[eid] [int] NULL,
[name] [varchar](50) NULL,
[sal] [money] NULL,
[doj] [date] NULL,
[deptno] [int] NULL
)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (1, N'a', 100.0000, CAST(N'2010-10-01' AS Date), 10)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (2, N'bb', 200.0000, CAST(N'2010-02-03' AS Date), 20)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (3, N'c', 300.0000, CAST(N'2017-02-03' AS Date), 30)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (4, N'd', 301.0000, CAST(N'2010-03-04' AS Date), 10)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (5, N'teee', 250.0000, CAST(N'2010-06-04' AS Date), 20)
INSERT [dbo].[Emp] ([eid], [name], [sal], [doj], [deptno])
VALUES (7, N'tte', 800.0000, CAST(N'2010-08-09' AS Date), 70)
I want output like below :
userlist
1,2,3,4,5,7
I tried this code:
select distinct
stuff((select ',' + cast(u.eid as varchar)
from emp u
where 1 = 1
for xml path('')), 1, 1, '') as userlist
from emp
Suppose if data has 100 thousand entries, then this query is not returning 100 thousand comma-separated
Could you please tell me how to write query to achieve this task in SQL Server?
I think the query is working as expected. But the result is too large to be displayed in management studio.

Get 'balanced' column value as 'Y' if both rows has same amt and 'N' if not in SQL query

I have number of CR records and DR records against the same id ,
I need to check sum of DR amount matches with the sum of CR amount for the same id if CR matches with DR then display Balanced column as "Y" else "N"
Required Result: Balanced" column value 'Y' if the Credit and Debit amt column matches and 'N' if they mismatch
Note: single query is needed for this:
As shown in above screen grab red highlighted result is required .
Script is given below :
USE [data]
GO
/****** Object: Table [dbo].[BankData] Script Date: 04-05-2018 3.54.46 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[BankData](
[ID] [int] NOT NULL,
[Name] [nchar](10) NULL,
[Amt] [decimal](18, 0) NULL,
[Type] [char](10) NULL,
[TransId] [int] IDENTITY(1,1) NOT NULL,
[CustId] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[Customer] Script Date: 04-05-2018 3.54.46 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customer](
[CustId] [int] NULL,
[Address] [nvarchar](50) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[BankData] ON
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (1, N'YASH ', CAST(300 AS Decimal(18, 0)), N'DR ', 1, 1)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (1, N'YASH ', CAST(300 AS Decimal(18, 0)), N'CR ', 2, 1)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(120 AS Decimal(18, 0)), N'DR ', 3, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(140 AS Decimal(18, 0)), N'CR ', 4, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (3, N'RAHUL ', CAST(100 AS Decimal(18, 0)), N'CR ', 5, 3)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (3, N'RAHUL ', CAST(100 AS Decimal(18, 0)), N'DR ', 6, 3)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (4, N'DINESH ', CAST(900 AS Decimal(18, 0)), N'CR ', 7, 4)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (4, N'DINESH ', CAST(900 AS Decimal(18, 0)), N'DR ', 8, 4)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(30 AS Decimal(18, 0)), N'DR ', 9, 2)
INSERT [dbo].[BankData] ([ID], [Name], [Amt], [Type], [TransId], [CustId]) VALUES (2, N'FALE ', CAST(130 AS Decimal(18, 0)), N'DR ', 10, 2)
SET IDENTITY_INSERT [dbo].[BankData] OFF
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (1, N'Mumbai')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (2, N'Delhi')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (3, N'Pune')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (4, N'Banglore')
INSERT [dbo].[Customer] ([CustId], [Address]) VALUES (5, N'Surat')
If 2012+, this is a small matter using the window function sum() over
Example
Select *
,Balanced = IIF(sum(Amt * IIF([Type]='CR',-1,1)) over (Partition By ID) =0,'Y','N')
from [BankData]
Returns
ID Name Amt Type TransId CustId Balanced
1 YASH 300 DR 1 1 Y
1 YASH 300 CR 2 1 Y
2 FALE 120 DR 3 2 N
2 FALE 140 CR 4 2 N
2 FALE 30 DR 9 2 N
2 FALE 130 DR 10 2 N
3 RAHUL 100 CR 5 3 Y
3 RAHUL 100 DR 6 3 Y
4 DINESH 900 CR 7 4 Y
4 DINESH 900 DR 8 4 Y
I use in-query to get the Balanced column. I group by ID then get the sum of Amt. If type is CR then it is negative (-1*Amt) and if DR it is positive. Then I did a query for table bankData and assign it to it's own ID (t1.ID=t.ID). If sum is zero then it is balanced='Y' else it is not ('N').
select [ID], [Name], [Amt], [Type], [TransId], [CustId],
(select case when sum(case when [Type]='DR' then [Amt] else -1*[Amt] end)=0
then 'Y'
else 'N' end
from [dbo].[BankData] as t1
where t1.[ID] = t.[ID]
group by t1.[ID]) as Balanced
from [dbo].[BankData] as t
order by t.[ID], t.[TransId]

SQL Order the rows

This is the following db structure i have, here the issue we are facing to order the rows based on the filed wise.
Field - table hold the field information ed, 2002,2015, Region 1 etc
IndicatorData- hold the row data
datafield - relationship with IndicatorData table... row can have multiple fields
/****** object: table [dbo].[indicatordata] ******/
create table [dbo].[indicatordata](
[id] [bigint] null,
[value] [decimal](18, 2) null,
[hopevalue] [decimal](18, 2) null,
[indicatorid] [int] null,
[datakind] [int] null
) on [primary]
go
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195045, cast(70.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195046, cast(40.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195047, cast(5.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195048, cast(100.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195049, cast(87.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
insert [dbo].[indicatordata] ([id], [value], [hopevalue], [indicatorid], [datakind]) values (195050, cast(9.00 as decimal(18, 2)), cast(0.00 as decimal(18, 2)), 2032, 0)
/****** object: table [dbo].[indicator] ******/
go
create table [dbo].[indicator](
[id] [int] null,
[name] [varchar](50) null
) on [primary]
go
insert [dbo].[indicator] ([id], [name]) values (2032, n'test tile')
/****** object: table [dbo].[field] ******/
go
create table [dbo].[field](
[id] [int] null,
[name] [varchar](255) null,
[rank] [int] null,
[parentid] [int] null
) on [primary]
go
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (120, n'2006', 18, 57)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (63, n'2015', 17, 57)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (303, n'2007', 9, 57)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (168, n'2018', 20, 57)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (1463, n'region 1', 1, 1459)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (1461, n'region 2', 3, 1459)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (57, n'year', 0, 0)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (1459, n'region', 0, 0)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (315, n'2002', 1, 57)
insert [dbo].[field] ([id], [name], [rank], [parentid]) values (123, n'2017', 19, 57)
/****** object: table [dbo].[datafields] ******/
set ansi_nulls on
go
create table [dbo].[datafields](
[dataid] [int] null,
[fieldid] [int] null
) on [primary]
go
insert [dbo].[datafields] ([dataid], [fieldid]) values (195045, 120)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195045, 1463)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195046, 63)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195046, 1461)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195047, 303)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195047, 1463)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195048, 168)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195048, 1463)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195049, 315)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195049, 1463)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195050, 123)
insert [dbo].[datafields] ([dataid], [fieldid]) values (195050, 1463)
go
Here is the query that i have tried to archive it. but its fail
select fieldid, groupedData.value as value, groupedData.hopeValue as hopeValue,
groupedData.datakind, groupedData.id as id, FieldSelector.name,
groupedData.rank
from DataFields FieldsToInsert
join (
select d.id id,min(d.datakind) as datakind, sum(rank) rank, min(value) value, min(hopeValue) hopeValue
from indicatorData d join datafields df on d.id = df.dataid
join field f on df.fieldId=f.id where indicatorId=2032
group by d.id) groupedData on FieldsToInsert.dataid = groupedData.id
join Field FieldSelector on FieldSelector.id=FieldsToInsert.fieldId
order by groupedData.rank asc, groupedData.id
Output we got it is
View Image
Expecting the output is
View image
So the first thought that strikes me is "Is the data correct?" I ask because looking at the years and rank values it suggests that 2006 should maybe be 2016 or the rank for 2006 should be 8 instead of 18.
That aside, and assuming the data is correct, you need to associate the region with the appropriate year. You can do this by getting the parent name for the field record and including the fieldid and then self joining back to get the associated year for that fieldid region record as follows...
WITH GroupedData AS
( SELECT d.id id,
min(d.datakind) AS datakind,
sum(f.rank) rank,
min(d.value) value,
min(d.hopevalue) hopeValue
FROM indicatordata d
JOIN datafields df ON d.id = df.dataid
JOIN field f ON df.fieldid = f.id
WHERE d.indicatorid = 2032
GROUP BY d.id
)
, df_parentType AS
( SELECT df.dataid,
df.fieldid,
f.name,
f.rank,
f.parentid,
fy.name AS parentname
FROM dbo.datafields AS df
JOIN field AS f ON df.fieldid = f.Id
JOIN field AS fy ON f.parentId = fy.Id
)
, df_yearregionmatched AS
( SELECT df.dataid,
df.fieldid,
df.name,
df.rank,
dfp.name AS yearname,
CASE df.parentname WHEN 'year' THEN 0 ELSE 1 END AS datafieldtype
FROM df_parentType AS df
JOIN df_parentType AS dfp ON dfp.dataid = df.dataid AND dfp.parentname = 'year'
)
SELECT GroupedData.id AS fieldid,
GroupedData.value AS value,
GroupedData.hopeValue AS hopeValue,
GroupedData.datakind,
GroupedData.id AS id,
FieldSelector.name,
GroupedData.rank,
FieldSelector.yearname,
FieldSelector.datafieldtype
FROM GroupedData
JOIN df_yearregionmatched FieldSelector ON GroupedData.id = FieldSelector.dataid
ORDER BY FieldSelector.yearname,
FieldSelector.datafieldtype;
I have used CTEs to keep the code uncomplicated. The ordering then is simply by yearname and a generated value to put year before region.
#nickFry
Check another with complex example with one more field...
create table indicator(id int not null,name varchar(255) not null)
insert indicator (id, name) values (1, 'basic employee details')
create table fields(
id int not null,
rank int,
name varchar(255) not null,
parentid int not null)
insert fields (id, rank, name, parentid) values (1, 0, 'year', 0)
insert fields (id, rank, name, parentid) values (2, 1, '2010', 1)
insert fields (id, rank, name, parentid) values (5, 2, '2011', 1)
insert fields (id, rank, name, parentid) values (6, 3, '2012', 1)
insert fields (id, rank, name, parentid) values (7, 4, '2013', 1)
insert fields (id, rank, name, parentid) values (8, 5, '2014', 1)
insert fields (id, rank, name, parentid) values (9, 0, 'nationality', 0)
insert fields (id, rank, name, parentid) values (10, 1, 'libya', 9)
insert fields (id, rank, name, parentid) values (11, 2, 'ukrine', 9)
insert fields (id, rank, name, parentid) values (12, 0, 'gender', 0)
insert fields (id, rank, name, parentid) values (13, 1, 'male', 12)
insert fields (id, rank, name, parentid) values (14, 2, 'fe male', 12)
insert fields (id, rank, name, parentid) values (15, 0, 'maritalstatus', 0)
insert fields (id, rank, name, parentid) values (16, 1, 'married', 15)
insert fields (id, rank, name, parentid) values (17, 2, 'unmarried', 15)
insert fields (id, rank, name, parentid) values (18, 3, 'divorced', 15)
create table indicatorfields(
indicatorid int not null,
fieldid int not null,rank int)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 2,1)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 5,1)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 6,1)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 7,1)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 8,1)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 10,3)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 11,3)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 16,2)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 17,2)
insert indicatorfields (indicatorid, fieldid,rank) values (1, 18,2)
create table indicatordata(
dataid int not null,
value varchar(255) not null,
indicatorid int not null)
insert indicatordata (dataid, value, indicatorid) values (1, '1015', 1)
insert indicatordata (dataid, value, indicatorid) values (2, '15', 1)
insert indicatordata (dataid, value, indicatorid) values (3, '12', 1)
insert indicatordata (dataid, value, indicatorid) values (4, '187', 1)
insert indicatordata (dataid, value, indicatorid) values (5, '50', 1)
insert indicatordata (dataid, value, indicatorid) values (6, '65', 1)
create table datafields(
dataid int not null,
fieldid int not null)
insert datafields (dataid, fieldid) values (1, 8)
insert datafields (dataid, fieldid) values (1, 10)
insert datafields (dataid, fieldid) values (1, 16)
insert datafields (dataid, fieldid) values (2, 6)
insert datafields (dataid, fieldid) values (2, 11)
insert datafields (dataid, fieldid) values (2, 17)
insert datafields (dataid, fieldid) values (3, 7)
insert datafields (dataid, fieldid) values (3, 11)
insert datafields (dataid, fieldid) values (3, 17)
insert datafields (dataid, fieldid) values (4, 2)
insert datafields (dataid, fieldid) values (4, 11)
insert datafields (dataid, fieldid) values (4, 16)
insert datafields (dataid, fieldid) values (5, 8)
insert datafields (dataid, fieldid) values (5, 10)
insert datafields (dataid, fieldid) values (5, 18)
insert datafields (dataid, fieldid) values (6, 2)
insert datafields (dataid, fieldid) values (6, 10)
insert datafields (dataid, fieldid) values (6, 16)
We need to get rows based on the indicatorfield & fields table order by rank
See the attached image for
Actual Output
This is wat i am looking for
Expected OutPut
#Prasad, solution without reference to any hardcoded data value...
WITH GroupedData AS
( SELECT d.dataid id,
--min(d.datakind) AS datakind,
sum(f.rank) rank,
min(d.value) value --,
--min(d.hopevalue) hopeValue
FROM indicatordata d
JOIN datafields df ON d.dataid = df.dataid
JOIN fields f ON df.fieldid = f.id
WHERE d.indicatorid = 1
GROUP BY d.dataid
)
, df_parentType AS
( SELECT df.dataid,
df.fieldid,
f.name,
f.rank,
f.parentid,
fy.name AS parentname
FROM dbo.datafields AS df
JOIN fields AS f ON df.fieldid = f.Id
JOIN fields AS fy ON f.parentId = fy.Id
)
, df_parentmatched AS
( SELECT df.dataid,
df.fieldid,
df.name,
df.rank,
dfp.name AS parentname
FROM df_parentType AS df
JOIN df_parentType AS dfp ON dfp.dataid = df.dataid AND dfp.parentname = (SELECT DISTINCT parentname FROM df_parentType WHERE parentid = (SELECT min(dataid) FROM df_parentType))
)
SELECT GroupedData.id AS datadid,
GroupedData.value AS value,
--GroupedData.hopeValue AS hopeValue,
--GroupedData.datakind,
FieldSelector.fieldid,
FieldSelector.name,
GroupedData.rank,
FieldSelector.parentname
FROM GroupedData
JOIN df_parentmatched FieldSelector ON GroupedData.id = FieldSelector.dataid
ORDER BY FieldSelector.parentname,
GroupedData.rank,
FieldSelector.fieldid;
#nickFy
The one you provide is fine... With this complex example... expected order is not coming in the correct way
Here is another complex example without the year
insert indicator (id, name) values (2, 'testing employee details 2')
insert indicatorfields (indicatorid, fieldid,rank) values (2, 10,3)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 11,3)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 13,1)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 14,1)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 16,2)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 17,2)
insert indicatorfields (indicatorid, fieldid,rank) values (2, 18,2)
insert indicatordata (dataid, value, indicatorid) values (7, '1015', 2)
insert indicatordata (dataid, value, indicatorid) values (8, '15', 2)
insert indicatordata (dataid, value, indicatorid) values (9, '12', 2)
insert indicatordata (dataid, value, indicatorid) values (10, '187', 2)
insert indicatordata (dataid, value, indicatorid) values (11, '50', 2)
insert datafields (dataid, fieldid) values (7, 11)
insert datafields (dataid, fieldid) values (7, 13)
insert datafields (dataid, fieldid) values (7, 16)
insert datafields (dataid, fieldid) values (8, 10)
insert datafields (dataid, fieldid) values (8, 13)
insert datafields (dataid, fieldid) values (8, 17)
insert datafields (dataid, fieldid) values (9, 10)
insert datafields (dataid, fieldid) values (9, 14)
insert datafields (dataid, fieldid) values (9, 18)
insert datafields (dataid, fieldid) values (10, 11)
insert datafields (dataid, fieldid) values (10, 13)
insert datafields (dataid, fieldid) values (10, 16)
insert datafields (dataid, fieldid) values (11, 10)
insert datafields (dataid, fieldid) values (11, 14)
insert datafields (dataid, fieldid) values (11, 16)
**Acutal Output we got is **
select a.dataid,value,df.fieldid,name from indicatordata a INNER JOIN datafields df on a.dataid=df.dataid
INNER JOIN fields f ON df.fieldid=f.id INNER JOIN indicatorfields indFields ON indFields.fieldid=df.fieldid
where a.indicatorid=2 and indFields.indicatorid=2 order by a.dataid
We need to order the fields based on the indicatorfield & field table
Expected Output should be like this

Why isn't STUFF and FOR XML PATH not concenating?

I have these two tables
CREATE TABLE [dbo].[Things](
[testid] [int] NOT NULL,
[testdesc] [varchar](10) NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[ThingsStaging](
[otherid] [int] NOT NULL,
[testid] [int] NOT NULL
) ON [PRIMARY]
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (1, N'Stuff')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (2, N'Things')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (3, N'Orcs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (4, N'Grubs')
INSERT INTO [dbo].[Things] ([testid], [testdesc]) VALUES (5, N'Shrooms')
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 1)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 2)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (1, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 3)
INSERT INTO [dbo].[ThingsStaging] ([otherid], [testid]) VALUES (2, 4)
;with allThings(otherid, descs)
as
(
select ts.otherid ,
stuff ((select ', ' + blah.testdesc as [text()]
from (
select distinct t.testdesc
from Things as t
where t.testid = ts.testid ) as blah
for xml path('')), 1, 1, '') as stuffs
from ThingsStaging as ts
)
select *
from allThings
Now when run this query, I get
otherid stuffs
1 Stuff
1 Things
1 Orcs
2 Orcs
2 Grubs
But I should get:
otherid stuffs
1 Stuff, Things, Orcs
2 Orcs, Grubs
I'm not understanding what I'm doing wrong.
I understand what I did wrong. Code will explain better.
select otherid, stuff((select ', ' + t.testdesc as [text()]
from Things as t
inner join ThingsStaging as its on t.testid = its.testid
where its.otherid = ts.otherid
for xml path('')), 1, 1, '') as descs
from ThingsStaging as ts
group by otherid

Add not relevant column to group by script

This is my sample table and values:
CREATE TABLE [dbo].[Test]
(
[Id] BIGINT NOT NULL DEFAULT(0),
[VId] BIGINT NOT NULL DEFAULT(0),
[Level] INT NOT NULL DEFAULT(0)
);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (100, 1, 1);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (101, 1, 2);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (102, 1, 3);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (103, 2, 1);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (104, 3, 1);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (105, 3, 2);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (106, 4, 1);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (107, 4, 2);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (108, 4, 3);
INSERT INTO [dbo].[Test] ([Id], [VId], [Level]) VALUES (109, 4, 4);
So at now I use this script:
SELECT
[T].[VId], MAX ([T].[Level]) AS [MaxLevel]
FROM
[dbo].[Test] AS [T]
GROUP BY
[T].[VId];
And it returns:
VId MaxLevel
1 3
2 1
3 2
4 4
But I need Id column also and I can't add it to Group by script, I need the following values:
VId MaxLevel Id
1 3 102
2 1 103
3 2 105
4 4 109
What is your suggestion?
Also The following values is enough The Id's With Max(Level) in any VId :
Id
102
103
105
109
A 2008 take on the question, since that's what you're working with:
declare #Test table
(
[Id] BIGINT NOT NULL DEFAULT(0),
[VId] BIGINT NOT NULL DEFAULT(0),
[Level] INT NOT NULL DEFAULT(0)
);
INSERT INTO #Test ([Id], [VId], [Level])
VALUES (100, 1, 1),(101, 1, 2),(102, 1, 3),(103, 2, 1),(104, 3, 1),
(105, 3, 2),(106, 4, 1),(107, 4, 2),(108, 4, 3),(109, 4, 4);
;With Numbered as (
select *,
RANK() OVER (PARTITION BY VId ORDER BY [Level] desc) as rn
from #Test)
select VId,Level,Id from Numbered where rn=1
Note that (as with the other solutions) this will output multiple rows per VId if there are two rows with the same maximum level. If you don't want that, switch RANK() to ROW_NUMBER() and an arbitrary one will win - or if you want a specific winner in the case of a tie, add that condition into the ORDER BY of the window function.
Use joining with the same table by VId column
something like this:
SELECT [T].[VId], [T].[MaxLevel], [T1].[Id]
FROM [dbo].[Test] AS [T1] JOIN
(SELECT [T].[VId], MAX ([T].[Level]) AS [MaxLevel]
FROM [dbo].[Test] AS [T]
GROUP BY [T].[VId]) AS [T]
ON [T1].[VId] = [T].[VId]
AND [T1].[Level] = [T].[MaxLevel]
ORDER BY [T].[VId];
the result will be:
VId MaxLevel Id
1 3 102
2 1 103
3 2 105
4 4 109
Use this:
WITH LastLevels AS
(
SELECT
[T].[VId] AS [VID],
MAX ([T].[Level]) AS [MaxLevel]
FROM [dbo].[Test] AS [T]
GROUP BY [T].[VId]
)
SELECT [LastLevels].[VID],[LastLevels].[MaxLevel], [Te].[Id]
FROM [dbo].[Test] AS [Te]
INNER JOIN [LastLevels]
ON [LastLevels].[VID]=[Te].[VId]
AND [LastLevels].[MaxLevel]=[Te].[Level]
ORDER BY [LastLevels].[VID];
SELECT ID, [VId], [MaxLevel] From
(
SELECT
[T].[VId], MAX ([T].[Level]) AS [MaxLevel]
FROM
[dbo].[Test] AS [T]
GROUP BY
[T].[VId]
)K
INNER JOIN [Test] T on T.[VId] = K.[VId] and T.[Level] = K.MaxLevel