Can anyone help me with a GROUP BY issue? - sql

I have this query:
SELECT
tc.dv_task,
tc.dv_ci_item,
STUFF((
SELECT ',' + lob.name
FROM u_cmdb_ci_line_of_business lob
where lob.sys_id = tc.ci_item
GROUP BY tc.dv_task
FOR XML PATH('') ), 1, 1, '') AS LOBs
FROM task_ci tc
INNER JOIN u_cmdb_ci_line_of_business lob on tc.ci_item = lob.sys_id
It returns the following error: Msg 164, Level 15, State 1, Line 8
Each GROUP BY expression must contain at least one column that is not an outer reference.
I'm using Microsoft SQL Server 2016 (SP2-GDR) (KB4505220) - 13.0.5101.9 (X64)
Here's what I'm trying to accomplish: I have two tables task_ci (tc) and u_cmdb_line_of_business (lob). The tables join by tc.ci_item = lob.sys_id. For each dv_task on the tc table, I want one line that lists, in a comma-separated field, the related ci_items from the lob table. That's why I'm trying to group by dv_task.
If I take out the group by, I get this:
tc.dv_task LOBs (Stuff field)
123456 lob.ci_item 1
123456 lob.ci_item 2
I want this:
dv_task LOBs (Stuff field)
123456 lob. ci_item 1, lob.ci_item 2
But when I add that group by, as an attempt to get things in one row, I get that error. Hope that makes sense.
Can anyone tell me what I'm doing wrong?
EDIT: 03/23
Okay, I got it, I just changed it up to substring like this
select
inc.number,
substring((select ', ' + lob.name from task_ci tc
join u_cmdb_ci_line_of_business lob on lob.sys_id = tc.ci_item
where inc.sys_id = tc.task
for XML PATH('')),2,1000) as lob_sysid
from incident inc
where inc.number = 'INC1157655'
I'm still not sure what I was doing wrong with the STUFF but I'll try it with the different table to see how it works.
Thanks for the help.

I don't think you need the JOIN in the outer query:
SELECT tc.dv_task, tc.dv_ci_item,
STUFF((SELECT ',' + lob.name
FROM u_cmdb_ci_line_of_business lob
WHERE lob.sys_id = tc.ci_item
FOR XML PATH('')
), 1, 1, '') AS LOBs
FROM task_ci tc;

Okay, I got it, I just changed it up to substring like this
select
inc.number,
substring((select ', ' + lob.name from task_ci tc
join u_cmdb_ci_line_of_business lob on lob.sys_id = tc.ci_item
where inc.sys_id = tc.task
for XML PATH('')),2,1000) as lob_sysid
from incident inc
where inc.number = 'INC1157655'
I'm still not sure what I was doing wrong with the STUFF but I'll try it with the different table to see how it works.
Thanks for the help.

Related

SQL server Stuff on multiple columns

I want to concatenate the value of multiple columns for the same ID.
I managed to concatenate for the first column, but when trying the same syntax for the second I'm having an error "The multi-part identifier EnqAct.[ActionID] could not be bound."
Example_Data_Result
Here I managed to group several MachineName together, as seen in "Column1" but I can't manage to group both the MachineName and Description in their own column
My working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
DetAct.[Description]
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[EnquiryID] = Enq.[EnquiryID]
INNER JOIN [dbo].[DetailsAction] DetAct
ON DetAct.[ActionID] = EnqAct.[ActionID]
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
DetAct.[Description]
My non working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
Stuff((SELECT ', ' + DetAct.[Description]
FROM [dbo].[DetailsAction] DetAct
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[ActionID] = DetAtc.[ActionID]
WHERE Enq.[EnquiryID] = EnqAct.[EnquiryID]
FOR XML PATH('')), 1, 2, '')
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description]
Both work the same way, I have a table Enquiry which will have an EnquiryID.
then in my table EnquiryAction or MachineEnquiry I will have entitys with an EnquiryID and an Action/Machine ID
Then in my DetailsAction/Machine Table I will have the Action/Machine ID, and the string I want to get and concatenate.
Why am I having an error and is it possible to achieve what I'm trying to do ?

How to make a query with group_concat in sql server/powerpivot

I need help on my query. I am trying to concatenate DonorIntent so that each BudgetNbr has a one to one relationship with the DonorIntnet field. Currently I am exlcuding the BudgetNbrs with multiple DonorIntent (820655 and 820885)
The below hasn't worked for me so any help would be great!
SELECT
vwGEGiftEndowmentSummary.BudgetNbr
,vwGEGiftEndowmentSummary.BudgetName
,ODSBudgetIndexCurrent.OrgCode
,ODSBudgetIndexCurrent.BudgetStatus
,DonorIntent = STUFF((
SELECT ',' + vwGEGiftEndowmentSummary.DonorIntent
FROM vwGEGiftEndowmentSummary di
WHERE di.BudgetNbr = vwGEGiftEndowmentSummary.BudgetNbr
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM
vwGEGiftEndowmentSummary
INNER JOIN SOMOrgDeptGroups
ON vwGEGiftEndowmentSummary.Org_dept = SOMOrgDeptGroups.OrgDeptLevel
INNER JOIN ODSBudgetIndexCurrent
ON vwGEGiftEndowmentSummary.BudgetNbr = ODSBudgetIndexCurrent.BudgetNbr
WHERE
SOMOrgDeptGroups.ExtFundExpGroup = N'ADMIN'
AND ODSBudgetIndexCurrent.BudgetType IN (N'06', N'54')
AND vwGEGiftEndowmentSummary.BudgetNbr NOT IN (N'820655', N'820885')
GROUP BY
vwGEGiftEndowmentSummary.BudgetNbr
,vwGEGiftEndowmentSummary.BudgetName
,DonorIntent
,ODSBudgetIndexCurrent.OrgCode
,ODSBudgetIndexCurrent.BudgetStatus
Question resolved. I needed to remove GROUP BY DonorIntent and place into the subquery

SQL Concatenation using XML Path - multiple rows with multiple table references

I am trying to use the XML Path to run SQL Concatenation but I am running into a bit of a problem. I have one table that is being used as a reference table for values I want to concatenate.I have 3 columns in the reference table (M.PROD, S.PROD, & REF NUMB).
M.PROD=====>S.PROD======>Ref Numb
1===========>_===========>981024583
2===========>_===========>981024719
3===========>A===========>981024605
3===========>B===========>981024669
4===========>A===========>981024688
4===========>B===========>981024706
4===========>C===========>981024723
5===========>_===========>981024742
6===========>_===========>981024742
I have the main tables where the m.prod and s.prod are used to match the reference table for Ref Numb values. What I want to do is concatenate the Ref Numb values based on what is being selected in main tables. The out put I am looking for is this:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024706, 981024723
5===========>981024742
6===========>981024742
I am using the following query:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P
This gives me the output of:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024706, 981024723
5===========>981024742
6===========>981024742
However, there are times where all the s.prod are not in the main tables. So for this I use this query:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT AND P1.SUBID = P.SUBID
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P
This query produces following output for me:
M.Prod======>Ref Numb
1===========>NULL
2===========>NULL
3===========>981024605
3===========>981024669
4===========>981024688
4===========>981024723
5===========>NULL
6===========>NULL
The output I need in these cases is:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024723
5===========>981024742
6===========>981024742
Any solution for this will be greatly appreciated, Thank you.
I'm not sure if I understood your question correctly, but try this:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT
AND (P1.SUBID = P.SUBID OR P1.SUBID IS NULL AND P.SUBID IS NULL)
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P

SQL Join then combine columns from the result

So I have two db2 tables. One contains work order information like id, requester name, user, description, etc. Second table that has notes, which is keyed to the id of the other table. The notes field is a 255 text field (Yeah don't suggest changing it, I have no control over it). So there could be multiple results, or none, in the note field depending on obviously how many notes there are.
I have a query which fetches the results. The problem is that I am getting multiple results form the join because there are multiple entries.
So my question is how do I concat/merge the results from the notes table into one field for every result? Thanks
Code:
SELECT
p.ABAANB AS WO_NUMBER,
p.ABAJTX AS Description,
i.AIAKTX as Notes
FROM
htedta.WFABCPP p LEFT JOIN HTEDTA.WFAICPP i
ON i.AIAANB = p.ABAANB
WHERE
p.ABABCD = 'ISST' AND p.ABAFD8 = 0
Have you tried LISTAGG
https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/listagg?lang=en
It will allow you to merge all those pesky fields that are causing the additional records... Something like this...
SELECT p.ABAANB AS WO_NUMBER, p.ABAJTX AS Description, LISTAGG(i.AIAKTX, ' ') as Notes
FROM htedta.WFABCPP p
LEFT JOIN HTEDTA.WFAICPP i
ON i.AIAANB = p.ABAANB
WHERE p.ABABCD = 'ISST'
AND p.ABAFD8 = 0
GROUP BY p.ABAAMB, p.ABAJTX
What version of DB2 are you on? If you're using DB2 Linux/Unix/Windows (LUW), then this should work for you:
SELECT p.ABAANB AS WO_NUMBER,
p.ABAJTX AS Description,
,SUBSTR(
xmlserialize(
xmlagg(
xmltext(
concat(',' , TRIM(i.AIAKTX))
)
) AS VARCHAR(4000)
)
,2) AS NOTES
FROM htedta.WFABCPP p
LEFT JOIN HTEDTA.WFAICPP i
ON i.AIAANB = p.ABAANB
WHERE p.ABABCD = 'ISST'
AND p.ABAFD8 = 0
GROUP BY p.ABAANB,
p.ABAJTX
If you are running DB2 at least 9.7, you should be able to use the XMLAGG function similar to this
WITH CombinedNotes( aiaanb, aiaktx) AS (
SELECT aiaanb
, REPLACE( REPLACE(
CAST( XML2CLOB(
XMLAGG( XMLELEMENT(
NAME 'A'
, aiaktx
))
) AS VARCHAR( 3000))
, '<A>',''), '</A>', '')
FROM Htedta.WfaIcpp)
SELECT p.ABAANB AS WO_NUMBER, p.ABAJTX AS Description, i.AIAKTX as Notes
FROM htedta.WFABCPP p
LEFT JOIN CombinedNotes i
ON i.AIAANB = p.ABAANB
WHERE p.ababcd = 'ISST'
AND p.abafd8 = 0;
If you have an earlier version of DB2, or your login for some reason does not permit the XML functions, you can solve the problem with a recursive query. Both techniques are described in the following blog
http://ibmmainframes.com/about44805.html

Query TFS database to fetch last 10 check-in details

Is there a way to query TFS database to get the last 10 check-in details
The output should be something like
File name | Comment | Changed By | Date
----------------------------------------------------------------------------
Test.cs Added new functionality username 01/08/2010
I am aware that the above result set can be obtained using TFS SDK. But I want to know if
there is a way to query the TFS database to fetch the above data.
Thanks
If I understand your question correctly, this will get you most of the way there in SQL:
SELECT TOP 10
V.ChildItem AS [File name],
CS.Comment,
I.DisplayName AS [Changed By],
CS.CreationDate AS [Date]
FROM tbl_Changeset CS
INNER JOIN tbl_Identity I ON I.IdentityID = CS.OwnerID
INNER JOIN tbl_Version V ON V.VersionFrom = CS.ChangesetID
ORDER BY CS.CreationDate DESC
There are some escaped characters in the file names that showed up while I was testing this on my TFS instance (like underscore characters become ">"). Other than that this should serve you well.
A lot of these queries are no longer relevant with newer instances of TFS. One of the big reasons is that the user identities (tbl_Identity) have been moved. Tfs_DefaultCollection is the DB that stored all information pertinent to a given Collection, but TFS can host multiple Collections AND an Admin can change the name of the default Collection when they are setting up TFS.
As such, all user identities have been moved to the Tfs_Configuration database;
select * from [tfs_Configuration].dbo.tbl_Identity
Gaining Access to the descriptive part of the account name ( AccountName or DisplayName ) from a Collection DB is accomplished by Join from [tfs_DefaultCollection].dbo.tbl_IdentityMap
select *
from [tfs_Configuration].dbo.tbl_Identity I
JOIN [tfs_DefaultCollection].dbo.tbl_IdentityMap IM
ON I.Id = IM.MasterID
With this information in hand, we can now produce the following query to show the last 100 ChangeSets committed to TFS as well as the name of the committer.
select top 100 *
from tbl_changeset as c
JOIN tbl_IdentityMap IM
ON C.OwnerID = IM.localId
JOIN tfs_configuration.dbo.tbl_Identity u
ON IM.MasterID = u.Id
Order by C.ChangeSetID DESC
Looking at this data, we can see A LOT of IDs, Sids, Lookups, etc. What we will NOT see in this data is any information about the File that was committed or information about the Branch the Commit was made to. This information comes from the tbl_Version table.
select top 100 *
from [tfs_DefaultCollection].dbo.tbl_changeset as c
JOIN [tfs_DefaultCollection].dbo.tbl_IdentityMap IM
ON C.OwnerID = IM.localId
JOIN [tfs_configuration].dbo.tbl_Identity u
ON IM.MasterID = u.Id
JOIN [tfs_DefaultCollection].dbo.tbl_Version as v
ON v.Versionfrom = c.ChangeSetId
Order by C.ChangeSetID DESC
[tfs_DefaultCollection].dbo.tbl_Version has a few columns of interest, namely; ParentPath, ChildItem & FullPath. What is missing here is any useful information regarding the Branch that the commit was made to. Branch info is embedded in either of the 2 available Path fields;
$\da3da7cf"80b5"4385"b3dc"ebb3088f3c01\Features\Inpatient\Source\Yadda\Yadda\Yadda\
This begs the next question, where is Branch info stored in TFS? Thanks to StackOverflowUsers answer above, this information was found in [tfs_DefaultCollection].dbo.TreeNodes table;
select * from [tfs_DefaultCollection].dbo.[TreeNodes] where parentID=0 and fDeleted=0
The Column CssNodeID is the ID we are looking for to make sense out of the FullPath
CoolBranchName da3da7cf-80b5-4385-b3dc-ebb3088f3c01
However, this presents us with our next challenge regarding the TFS Databases. A lot of information is encoded and\or embedded so we need to manipulate a few things to get what we are after.
In this instance, the part of the [tfs_DefaultCollection].dbo.tbl_Version.ParentPath or [tfs_DefaultCollection].dbo.tbl_Version.FullPath value that contains the Branch info.
This ugly little diddy right here extracts the ID portion of the ParentPath field value and replaces all the Double-Quotes with Hyphens which gives us an Id value we can use to query [Tfs_DefaultCollection].dbo.TreeNodes
SUBSTRING(
REPLACE( v.ParentPath, '$\', ''),
CHARINDEX( '\', REPLACE( v.ParentPath, '$\', '') ),
( LEN( v.ParentPath ) - CHARINDEX( '\', REPLACE( v.ParentPath, '$\', '') ) )
)
Putting all of this together in pursuit of a Query to Fetch The Last [X] Check-In details results in the following;
select top 10
c.CreationDate,
c.Comment,
u.DisplayName as CommittingUser,
TN.Name as BranchName,
SUBSTRING(
REPLACE( v.ParentPath, '$\', ''),
CHARINDEX( '\', REPLACE( v.ParentPath, '$\', '') ),
( LEN( v.ParentPath ) - CHARINDEX( '\', REPLACE( v.ParentPath, '$\', '') ) )
) as ChangedFile
from tbl_changeset as c
JOIN tbl_IdentityMap IM
ON C.OwnerID = IM.localId
JOIN [Tfs_Configuration].dbo.tbl_Identity u
ON IM.MasterID = u.Id
JOIN dbo.tbl_Version as v
ON v.Versionfrom = c.ChangeSetId
LEFT JOIN dbo.TreeNodes TN with(nolock)
ON TN.CssNodeId = REPLACE(
SUBSTRING(
REPLACE( v.ParentPath, '$\', ''),
0,
CHARINDEX( '\', REPLACE( v.ParentPath, '$\', '') )
),
'"', '-'
)
AND parentID=0
AND fDeleted=0
Order by c.CreationDate desc
Note that I included the DB qualifiers for all the queries leading up to the final query to provide context on where tables of interest are located.
As a workaround how about the below query.. But i think it is returning me the wrong comments.. not sure why.
SELECT top 10
C.ChangeSetId,
V.FullPath,
V.ParentPath,
REPLACE(V.ChildItem,'\','') as [FileName],
C.CreationDate,
I.DisplayName,
C.Comment
FROM tbl_Version(nolock) V
INNER JOIN tbl_File (nolock) F ON V.ItemId = F.ItemId
INNER JOIN tbl_Changeset (nolock) C ON V.VersionTo = C.ChangeSetId
INNER JOIN tbl_Identity (nolock) I ON C.CommitterId = I.IdentityId
where v.ParentPath like '$\' + (select name from [TfsWorkItemTracking].[dbo].[treenodes] where parentid=0 and fdeleted=0 and id=524) + '\%'
order by C.CreationDate desc
Thanks to mark.crockett for posting the above query # http://social.msdn.microsoft.com/Forums/en-US/tfsreporting/thread/32d2c27e-825b-43bb-b156-36048a3e70cb/
If you have access to the SQL server that hosts TFS database the db you have to look is TFSWarehouse, then you can look for the tables Work Item,tbl_Changeset,tbl_Identity,tbl_Version etc. from where you can pull some information.
Thnks.