http://sqlfiddle.com/#!3/e4891/1
for the above resulting query(which pivots data) I want to run my one more select condition.
For example
select (C1 & C2) from ‘the above pivoted query results’
IS it possible to do it? CTE will help here?
SQL Server 2008 and above.
Try this:
WITH Data AS
(
select *
from
(
select MemId, Condition_id, condition_result
from t
) x
pivot
(
sum(condition_result)
for condition_id in ([C1], [C2], [C3], [C4])
) p
)
SELECT C1, C2
FROM Data
SQLFiddle: http://sqlfiddle.com/#!3/e4891/3
either change your select to only select the fields that you want:
select [C1], [C2]
from
(
select MemId, Condition_id, condition_result
from t
) x
pivot
(
sum(condition_result)
for condition_id in ([C1], [C2], [C3], [C4])
) p
OR
;with cte
as
(
select *
from
(
select MemId, Condition_id, condition_result
from t
) x
pivot
(
sum(condition_result)
for condition_id in ([C1], [C2], [C3], [C4])
) p
)
select [C1], [C2]
from cte
Related
Is there a way to get a unique ID for each [Group] to be generated dynamically? I have tried newid() but the result is a different value for each row. The intent is to not have to worry about adding a unique value for each set of T (as indicated by the set which is commented out). (The initial character for each value of [Value] (ex., 1) corresponds to the hard-coded value of [Group] only for readability purposes when viewing the results.)
select
[Name],
[Value],
[Group]
from (
select
[Name],
[Value],
1 as [Group] --newid() as [Group] --
from (
values
('abc', '1qwert'),
('def', '1yuiop')
) as T ([Name], [Value])
union all
select
[Name],
[Value],
2 as [Group] --newid() as [Group] --
from (
values
('abc', '2asdfg'),
('def', '2hjkl')
) as T ([Name], [Value])
union all
select
[Name],
[Value],
3 as [Group] --newid() as [Group] --
from (
values
('abc', '3zxcv'),
('def', '3bnm')
) as T ([Name], [Value])
--union all
--select
-- [Name],
-- [Value],
-- ? as [Group] --newid() as [Group] --
--from (
-- values
-- ('abc', '?poiuy'),
-- ('def', '?trewq')
-- ) as T ([Name], [Value])
) as TT
order by
[Group],
[Name];
Generally speaking, the function NEWID() generate the unique value for every row, when we put it as a column in the select list:
select
NEWID() as column_name
from table
There is a common, well known issue with the strange behavior of the function NEWID().
So we actually can't force query optimizer to materialize NEWID() value inside from clause:
select
t.*,
t2.col
from table t
cross join (select NEWID() as col) t2
In this case we get again the same unique values for every row.
Still, we have to find a way to force optimizer to calculate the NEWID() value inside the from clause.
As we know from logical query processing order the "ORDER" operator executed almost at the end of the query, after SELECT clause. We have to know values before we would like to sort them.
So first, we should somehow sort "select" statement inside query by NEWID() value.
The only legal possibility to do this is to add TOP 1 operator.
Second, to be sure that the optimizer won't skip ordering due to only 1 value, we add another NEWID() value.
So, to every union select we should add:
cross join (select top 1 t.group_id from (values (NEWID()), (NEWID()))as t(group_id) ORDER BY group_id) as tt
In this case the optimizer should, no matter what, sort values, which it should know beforehand.
And the query looks like this:
select
[Name],
[Value],
[Group]
from (
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '1qwert'),
('def', '1yuiop')
) as T ([Name], [Value])
cross join (select top 1 t.group_id from (values (NEWID()), (NEWID()))as t(group_id) ORDER BY group_id) as tt
union all
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '2asdfg'),
('def', '2hjkl')
) as T ([Name], [Value])
cross join (select top 1 t.group_id from (values (NEWID()), (NEWID()))as t(group_id) ORDER BY group_id) as tt
union all
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '3zxcv'),
('def', '3bnm')
) as T ([Name], [Value])
cross join (select top 1 t.group_id from (values (NEWID()), (NEWID()))as t(group_id) ORDER BY group_id) as tt
) as t
In this case, we shouldn't materialize random unique values in the table.
And the final correction is to add
select top 1 t.group_id from (values (NEWID()), (NEWID()))as t(group_id) ORDER BY group_id
into CTE.
The final query will look like this:
;with unique_group as (
select top 1
t.group_id
from (values
(NEWID()),
(NEWID())
)as t(group_id)
order by group_id
)
select
[Name],
[Value],
[Group]
from (
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '1qwert'),
('def', '1yuiop')
) as T ([Name], [Value])
cross join unique_group as tt
union all
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '2asdfg'),
('def', '2hjkl')
) as T ([Name], [Value])
cross join unique_group as tt
union all
select
[Name],
[Value],
tt.group_id as [Group]
from (
values
('abc', '3zxcv'),
('def', '3bnm')
) as T ([Name], [Value])
cross join unique_group as tt
) as t
Give each subquery within your union a unique reference number, relate that number to a small set of newid() values that also share the same set of integers.
;with cte as (
select 1 as gid, newid() as [group]
union all
select gid + 1, newid()
from cte
where gid < 3
)
select
[Name],[Value],[Group]
from (
select
[Name],[Value], 1 as gid
from (
values
('abc', '1qwert'),
('def', '1yuiop')
) as T ([Name], [Value])
union all
select
[Name],[Value], 2 as gid
from (
values
('abc', '2asdfg'),
('def', '2hjkl')
) as T ([Name], [Value])
union all
select
[Name], [Value], 3 as gid
from (
values
('abc', '3zxcv'),
('def', '3bnm')
) as T ([Name], [Value])
) d
inner join cte on d.gid = cte.gid
see: https://rextester.com/IEPJC57700
+----+------+--------+--------------------------------------+
| | Name | Value | Group |
+----+------+--------+--------------------------------------+
| 1 | abc | 1qwert | 68f1884f-c3af-44b6-9856-2ca71615e4aa |
| 2 | def | 1yuiop | 68f1884f-c3af-44b6-9856-2ca71615e4aa |
| 3 | abc | 2asdfg | bf36a235-ef68-4c02-a502-8ba0009aa302 |
| 4 | def | 2hjkl | bf36a235-ef68-4c02-a502-8ba0009aa302 |
| 5 | abc | 3zxcv | 221ca4d2-ed7f-4654-9234-7081360f693c |
| 6 | def | 3bnm | 221ca4d2-ed7f-4654-9234-7081360f693c |
+----+------+--------+--------------------------------------+
I need to get a tree of related nodes given a certain node, but not necessary top node. I've got a solution using two CTEs, since I am struggling to squeeze it all into one CTE :). Might somebody have a sleek solution to avoid using two CTEs? Here is some code that I was playing with:
DECLARE #temp AS TABLE (ID INT, ParentID INT)
INSERT INTO #temp
SELECT 1 ID, NULL AS ParentID
UNION ALL
SELECT 2, 1
UNION ALL
SELECT 3, 2
UNION ALL
SELECT 4, 3
UNION ALL
SELECT 5, 4
UNION ALL
SELECT 6, NULL
UNION ALL
SELECT 7, 6
UNION ALL
SELECT 8, 7
DECLARE #startNode INT = 4
;WITH TheTree (ID,ParentID)
AS (
SELECT ID, ParentID
FROM #temp
WHERE ID = #startNode
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN TheTree tr ON t.ParentID = tr.ID
)
SELECT * FROM TheTree
;WITH Up(ID,ParentID)
AS (
SELECT t.id, t.ParentID
FROM #temp t
WHERE t.ID = #startNode
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN Up c ON t.id = c.ParentID
)
--SELECT * FROM Up
,TheTree (ID,ParentID)
AS (
SELECT ID, ParentID
FROM Up
WHERE ParentID is null
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN TheTree tr ON t.ParentID = tr.ID
)
SELECT * FROM TheTree
thanks
Meh. This avoids using two CTEs, but the result is a brute force kludge that hardly qualifies as "sleek" as it won’t be efficient if your table is at all sizeable. It will:
Recursively build all possible hierarchies
As you build them, flag the target NodeId as you find it
Return only the targeted tree
I threw in column “TreeNumber” on the off-chance the TargetId appears in multiple hierarchies, or if you’d ever have multiple values to check in one pass. “Depth” was added to make the output a bit more legible.
A more complex solution like #John’s might do, and more and subtler tricks could be done with more detailed table sturctures.
DECLARE #startNode INT = 4
;WITH cteAllTrees (TreeNumber, Depth, ID, ParentID, ContainsTarget)
AS (
SELECT
row_number() over (order by ID) TreeNumber
,1
,ID
,ParentID
,case
when ID = #startNode then 1
else 0
end ContainsTarget
FROM #temp
WHERE ParentId is null
UNION ALL
SELECT
tr.TreeNumber
,tr.Depth + 1
,t.id
,t.ParentID
,case
when tr.ContainsTarget = 1 then 1
when t.ID = #startNode then 1
else 0
end ContainsTarget
FROM #temp t
INNER JOIN cteAllTrees tr
ON t.ParentID = tr.ID
)
SELECT
TreeNumber
,Depth
,ID
,ParentId
from cteAllTrees
where TreeNumber in (select TreeNumber from cteAllTrees where ContainsTarget = 1)
order by
TreeNumber
,Depth
,ID
Here is a technique where you can select the entire hierarchy, a specific node with all its children, and even a filtered list and how they roll.
Note: See the comments next to the DECLAREs
Declare #YourTable table (id int,pt int,name varchar(50))
Insert into #YourTable values
(1,null,'1'),(2,1,'2'),(3,1,'3'),(4,2,'4'),(5,2,'5'),(6,3,'6'),(7,null,'7'),(8,7,'8')
Declare #Top int = null --<< Sets top of Hier Try 2
Declare #Nest varchar(25) = '|-----' --<< Optional: Added for readability
Declare #Filter varchar(25) = '' --<< Empty for All or try 4,6
;with cteP as (
Select Seq = cast(1000+Row_Number() over (Order by name) as varchar(500))
,ID
,pt
,Lvl=1
,name
From #YourTable
Where IsNull(#Top,-1) = case when #Top is null then isnull(pt,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',1000+Row_Number() over (Order by r.name)) as varchar(500))
,r.ID
,r.pt
,p.Lvl+1
,r.name
From #YourTable r
Join cteP p on r.pt = p.ID)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select Distinct
A.R1
,B.R2
,A.ID
,A.pt
,A.Lvl
,name = Replicate(#Nest,A.Lvl-1) + A.name
From cteR1 A
Join cteR2 B on A.ID=B.ID
Join (Select R1 From cteR1 where IIF(#Filter='',1,0)+CharIndex(concat(',',ID,','),concat(',',#Filter+','))>0) F on F.R1 between A.R1 and B.R2
Order By A.R1
Suppose that I have this query:
select *
from myTable
where myTable.myCol in (1,2,3)
I would like to do that:
with allowed_values as (1,2,3)
select *
from myTable
where myTable.myCol in allowed_values
It gives me a Syntax Error in the first row, can you help me fixing it?
The closest I can think to your syntax:
WITH allowed_values (id) AS
( VALUES
(1), (2), (3)
)
SELECT *
FROM myTable
WHERE id IN
(TABLE allowed_values) ;
Tested in SQL-Fiddle
Close to what you probably had in mind:
WITH allowed_values AS (SELECT '{1,2,3}'::int[] AS arr)
SELECT *
FROM my_table
,allowed_values -- cross join with a single row
WHERE my_col = ANY (arr);
Better:
WITH allowed_values (my_col) AS (VALUES (1), (2), (3))
SELECT *
FROM allowed_values
JOIN my_table USING (my_col)
But really, you can just simplify:
SELECT *
FROM (VALUES (1), (2), (3)) AS allowed_values (my_col)
JOIN my_table USING (my_col);
Try
with allowed_values as (select 1 as tst union all select 2 union all select 3)
select * from myTable a
inner join c1 b ON (b.tst = a.myCol)
The simplest way forward is to correct your common table expression, then use it in a subselect.
with allowed_values as (
select 1 id
union all
select 2
union all
select 3
)
select * from myTable
where myTable.id in (select id from allowed_values)
I have to make query on WITH query, something like
; WITH #table1
(
SELECT id, x from ... WHERE....
UNION ALL
SELECT id, x from ... WHERE...
)
WITH #table2
(
SELECT DISTINCT tbl_x.*,ROW_NUMBER() OVER (order by id) as RowNumber
WHERE id in ( SELECT id from #table1)
)
SELECT * FROM #table2 WHERE RowNumber > ... and ...
So I have to use WITH on WITH and then SELECT on second WITH, How I can do that?
You can define multiple CTEs after the WITH keyword by separating each CTE with a comma.
WITH T1 AS
(
SELECT id, x from ... WHERE....
UNION ALL
SELECT id, x from ... WHERE...
)
, T2 AS
(
SELECT DISTINCT tbl_x.*, ROW_NUMBER() OVER (order by id) as RowNumber
WHERE id in ( SELECT id from T1 )
)
SELECT * FROM T2 WHERE RowNumber > ... and ...
https://web.archive.org/web/20210927200924/http://www.4guysfromrolla.com/webtech/071906-1.shtml
I am using SSMS 2008 and trying to concatenate one of the rows together based on a different field's grouping. I have two columns, people_id and address_desc. They look like this:
address_desc people_id
---------- ------------
Murfreesboro, TN 37130 F15D1135-9947-4F66-B778-00E43EC44B9E
11 Mohawk Rd., Burlington, MA 01803 C561918F-C2E9-4507-BD7C-00FB688D2D6E
Unknown, UN 00000 C561918F-C2E9-4507-BD7C-00FB688D2D6E Jacksonville, NC 28546 FC7C78CD-8AEA-4C8E-B93D-010BF8E4176D
Memphis, TN 38133 8ED8C601-5D35-4EB7-9217-012905D6E9F1
44 Maverick St., Fitchburg, MA 8ED8C601-5D35-4EB7-9217-012905D6E9F1
Now I want to concatenate the address_desc field / people_id. So the first one here should just display "Murfreesboro, TN 37130" for address_desc. But second person should have just one line instead of two which says "11 Mohawk Rd., Burlington, MA 01803;Unknown, UN 00000" for address_desc.
How do I do this? I tried using CTE, but this was giving me ambiguity error:
WITH CTE ( people_id, address_list, address_desc, length )
AS ( SELECT people_id, CAST( '' AS VARCHAR(8000) ), CAST( '' AS VARCHAR(8000) ), 0
FROM dbo.address_view
GROUP BY people_id
UNION ALL
SELECT p.people_id, CAST( address_list +
CASE WHEN length = 0 THEN '' ELSE ', ' END + c.address_desc AS VARCHAR(8000) ),
CAST( c.address_desc AS VARCHAR(8000)), length + 1
FROM CTE c
INNER JOIN dbo.address_view p
ON c.people_id = p.people_id
WHERE p.address_desc > c.address_desc )
SELECT people_id, address_list
FROM ( SELECT people_id, address_list,
RANK() OVER ( PARTITION BY people_id ORDER BY length DESC )
FROM CTE ) D ( people_id, address_list, rank )
WHERE rank = 1 ;
Here was my initial SQL query:
SELECT a.address_desc, a.people_id
FROM dbo.address_view a
INNER JOIN (SELECT people_id
FROM dbo.address_view
GROUP BY people_id
HAVING COUNT(*) > 1) t
ON a.people_id = t.people_id
order by a.people_id
You can use FOR XML PATH('') like this:
DECLARE #TestData TABLE
(
address_desc NVARCHAR(100) NOT NULL
,people_id UNIQUEIDENTIFIER NOT NULL
);
INSERT #TestData
SELECT 'Murfreesboro, TN 37130', 'F15D1135-9947-4F66-B778-00E43EC44B9E'
UNION ALL
SELECT '11 Mohawk Rd., Burlington, MA 01803', 'C561918F-C2E9-4507-BD7C-00FB688D2D6E'
UNION ALL
SELECT 'Unknown, UN 00000', 'C561918F-C2E9-4507-BD7C-00FB688D2D6E'
UNION ALL
SELECT 'Memphis, TN 38133', '8ED8C601-5D35-4EB7-9217-012905D6E9F1'
UNION ALL
SELECT '44 Maverick St., Fitchburg, MA', '8ED8C601-5D35-4EB7-9217-012905D6E9F1';
SELECT a.people_id,
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM #TestData b
WHERE a.people_id = b.people_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
,2
,4000)
) GROUP_CONCATENATE
FROM #TestData a
GROUP BY a.people_id
Results:
people_id GROUP_CONCATENATE
------------------------------------ ------------------------------------------------------
F15D1135-9947-4F66-B778-00E43EC44B9E Murfreesboro, TN 37130
C561918F-C2E9-4507-BD7C-00FB688D2D6E 11 Mohawk Rd., Burlington, MA 01803;Unknown, UN 00000
8ED8C601-5D35-4EB7-9217-012905D6E9F1 Memphis, TN 38133;44 Maverick St., Fitchburg, MA