Want to fetch the data in the form of a table - sql

I have written this query:
SELECT
d.DetailId,
i.ItemId,
d.fieldId,
d.Fieldvalue,
f.Name
FROM
EntityItemDetails d
inner join EntityItems i
on i.ItemId = d.ItemId
inner join Fields f
on f.Id = d.FieldId
WHERE
i.EntityId = 1
Output is:
DetailId ItemId FieldId FieldValue FieldName
1 1 9 Defect1 Name
2 1 10 abcdef Description
5 1 11 testing123 Status
I want result in this way:
Name Description Status
TestField abcdef testing123
Please suggest how to get this result by writing a query in sql.

What you want is called pivoting, and starting from SQL Server 2005, you can use a standard syntax for pivoting in Transact-SQL, with the help of the PIVOT clause.
Your query could be transformed for use with PIVOT like this:
WITH source AS (
/* this CTE is actually your original query */
SELECT
EntityItemDetails.DetailId,
EntityItems.ItemId,
EntityItemDetails.fieldId,
EntityItemDetails.Fieldvalue,
Fields.Name
FROM EntityItemDetails
INNER JOIN EntityItems ON EntityItems.ItemId = EntityItemDetails.ItemId
INNER JOIN Fields ON Fields.Id = EntityItemDetails.FieldId
WHERE EntityItems.EntityId = 1
)
SELECT
ItemId,
Name,
Description,
Status
FROM (
SELECT ItemId, FieldName, FieldValue
FROM source
) s
PIVOT (
MAX(FieldValue) FOR FieldName IN (
Name,
Description,
Status
/* add other possible names as necessary */
)
) p

SELECT
FieldValue,
[Name],
[Description],
[Status]
FROM
myTable -- OR (your posted query) myQuery
PIVOT
(
MIN(FieldValue)
FOR FieldName IN ([Name], [Description], [Status])
) AS myPivot;

Tahnk u so much Andriy M....
with very few changes I could get the desired result. Chenges are as below
WITH source AS (
/* this CTE is actually your original query */
SELECT EntityItemDetails.CreatedDate, EntityItems.EntityItemId,
EntityItemDetails.fieldId,
EntityItemDetails.Fieldvalue,
Fields.Name FieldName FROM EntityItemDetails
INNER JOIN EntityItems ON EntityItems.EntityItemId = EntityItemDetails.EntityItemId
INNER JOIN Fields ON Fields.Id = EntityItemDetails.FieldId WHERE EntityItems.EntityId = 1 and (FieldId=9 or FieldId=10 or FieldId=11) )
SELECT EntityItemId, [Name], [Description], [Status]
FROM ( SELECT EntityItemId, FieldName, FieldValue FROM source ) s
PIVOT ( MAX(FieldValue) FOR FieldName IN ( [Name], [Description], [Status] ) ) p

Related

MS SQL recursively get child id with parent ids

I have created a search SQL query, I'm almost finished I only need to match the WHERE clause with an id and it's parent ids. Currently I only match with an id and not it's parents. I'm not sure how to solve this.
This is my query, the code where I need the change is where the comment "This part needs to match the tileid and it's parent tileids" is. Based on the [TileId] I need to get the [TileId] and it's parents.
WITH [TileSearch_CTE] ([TileId], [TypeId], [TypeName], [Title], [Info]) AS
(
SELECT TOP 10 [TileId], [TypeId], [TypeName], [Title], [Info]
FROM [Priox].[TileFullTextSearchNL]
INNER JOIN CONTAINSTABLE([Priox].[TileFullTextSearchNL], *, '"searchText*"') AS [CT]
ON [Priox].[TileFullTextSearchNL].[TileId] = [CT].[Key]
WHERE
(
NOT EXISTS
(
SELECT [intPortalTileFilterId]
FROM [Priox].[tblPortalTileFilter]
WHERE [intPortalTileIdFk] = [TileId] -- This part needs to match the tileid and it's parent tileids
)
OR EXISTS
(
SELECT [intPortalTileFilterId]
FROM [Priox].[tblPortalTileFilter]
WHERE [intPortalTileIdFk] = [TileId] -- This part needs to match the tileid and it's parent tileids
AND [intPortalFilterIdFk] IN (56)
)
)
ORDER BY [CT].[Rank] DESC
)
SELECT [TileId], [TypeName], [Title], [Info], [TP].[strName] AS [ParamName], [TPV].[strParamValue] AS [ParamValue]
FROM [TileSearch_CTE]
LEFT JOIN [Priox].[tblPortalTileParam] AS [TP] ON [TP].[intTileType] = [TileSearch_CTE].[TypeId]
LEFT JOIN [Priox].[tblPortalTileParamValue] AS [TPV] ON [TPV].[intTileParamIdFk] = [TP].[intPortalTileParamId] AND [TileSearch_CTE].[TileId] = [TPV].[intTileIdFk]
This is the database structure of the tiles.
So the query should do something like this.
SELECT [intPortalTileFilterId]
FROM [Priox].[tblPortalTileFilter]
WHERE [intPortalTileIdFk] IN (438,1317)
I fixed it myself, created a function that returns the parents and the child.
CREATE FUNCTION [Priox].[GetTileIdHierarchy]
(
#tileId int
)
RETURNS TABLE
AS
RETURN
(
WITH parents AS
(
SELECT [intPortalTileId], [intPortalTileId] AS [intParentIdFk]
FROM [Priox].[tblPortalTile] WHERE [intPortalTileId] = #tileId
UNION ALL
SELECT p.[intPortalTileId], [Priox].[tblPortalTile].[intParentIdFk]
FROM parents p
INNER JOIN [Priox].[tblPortalTile] on p.[intParentIdFk] = [Priox].[tblPortalTile].[intPortalTileId]
AND [Priox].[tblPortalTile].[intParentIdFk] IS NOT NULL
AND [Priox].[tblPortalTile].[intPortalTileId] <> [Priox].[tblPortalTile].[intParentIdFk]
)
SELECT [intPortalTileId], [intParentIdFk]
FROM parents
WHERE [intPortalTileId] = #tileId
)
GO
And changed my search query accordingly.
WITH [TileSearch_CTE] ([TileId], [TypeId], [TypeName], [Title], [Info], [Rank]) AS
(
SELECT TOP 10 [TileId], [TypeId], [TypeName], [Title], [Info],[CT].[Rank] AS [Rank]
FROM [Priox].[TileFullTextSearchNL]
INNER JOIN CONTAINSTABLE([Priox].[TileFullTextSearchNL], *, '"searchTerm*"') AS [CT]
ON [Priox].[TileFullTextSearchNL].[TileId] = [CT].[Key]
WHERE
(
NOT EXISTS
(
SELECT [intPortalTileFilterId]
FROM [Priox].[tblPortalTileFilter]
WHERE [intPortalTileIdFk] IN
(
SELECT [intParentIdFk] FROM [Priox].[GetTileIdHierarchy] ([TileId])
)
)
OR
EXISTS
(
SELECT [intPortalTileFilterId]
FROM [Priox].[tblPortalTileFilter]
WHERE [intPortalTileIdFk] IN
(
SELECT [intParentIdFk] FROM [Priox].[GetTileIdHierarchy] ([TileId])
)
AND [intPortalFilterIdFk] IN (51)
)
)
ORDER BY [CT].[Rank] DESC
)
SELECT [TileId], [TypeName], [Title], [Info], [TP].[strName] AS [ParamName], [TPV].[strParamValue] AS [ParamValue] , [Rank]
FROM [TileSearch_CTE]
LEFT JOIN [Priox].[tblPortalTileParam] AS [TP] ON [TP].[intTileType] = [TileSearch_CTE].[TypeId]
LEFT JOIN [Priox].[tblPortalTileParamValue] AS [TPV] ON [TPV].[intTileParamIdFk] = [TP].[intPortalTileParamId] AND [TileSearch_CTE].[TileId] = [TPV].[intTileIdFk]
I edited the starting post with the solution.

How to join three tables with distinct

I'm trying to join three tables to pull back a list of distinct blog posts with associated assets (images etc) but I keep coming up a cropper. The three tablets are tblBlog, tblAssetLink and tblAssets. The Blog tablet hold the blog, the asset table holds the assets and the Assetlink table links the two together.
tblBlog.BID is the PK in blog, tblAssets.AID is the PK in Assets.
This query works but pulls back multiple posts for the same record. I've tried to use select distinct and group by and even union but as my knowledge is pretty poor with SQL - they all error.
I'd like to also discount any assets that are marked as deleted (tblAssets.Deleted = true) but not hide the associated Blog post (if that's not marked as deleted). If anyone can help - it would be much appreciated! Thanks.
Here's my query so far....
SELECT dbo.tblBlog.BID,
dbo.tblBlog.DateAdded,
dbo.tblBlog.PMonthName,
dbo.tblBlog.PDay,
dbo.tblBlog.Header,
dbo.tblBlog.AddedBy,
dbo.tblBlog.PContent,
dbo.tblBlog.Category,
dbo.tblBlog.Deleted,
dbo.tblBlog.Intro,
dbo.tblBlog.Tags,
dbo.tblAssets.Name,
dbo.tblAssets.Description,
dbo.tblAssets.Location,
dbo.tblAssets.Deleted AS Expr1,
dbo.tblAssetLink.Priority
FROM dbo.tblBlog
LEFT OUTER JOIN dbo.tblAssetLink
ON dbo.tblBlog.BID = dbo.tblAssetLink.BID
LEFT OUTER JOIN dbo.tblAssets
ON dbo.tblAssetLink.AID = dbo.tblAssets.AID
WHERE ( dbo.tblBlog.Deleted = 'False' )
ORDER BY dbo.tblAssetLink.Priority, tblBlog.DateAdded DESC
EDIT
Changed the Where and the order by....
Expected output:
tblBlog.BID = 123
tblBlog.DateAdded = 12/04/2015
tblBlog.Header = This is a header
tblBlog.AddedBy = Persons name
tblBlog.PContent = *text*
tblBlog.Category = Category name
tblBlog.Deleted = False
tblBlog.Intro = *text*
tblBlog.Tags = Tag, Tag, Tag
tblAssets.Name = some.jpg
tblAssets.Description = Asset desc
tblAssets.Location = Location name
tblAssets.Priority = True
Use OUTER APPLY:
DECLARE #b TABLE ( BID INT )
DECLARE #a TABLE ( AID INT )
DECLARE #ba TABLE
(
BID INT ,
AID INT ,
Priority INT
)
INSERT INTO #b
VALUES ( 1 ),
( 2 )
INSERT INTO #a
VALUES ( 1 ),
( 2 ),
( 3 ),
( 4 )
INSERT INTO #ba
VALUES ( 1, 1, 1 ),
( 1, 2, 2 ),
( 2, 1, 1 ),
( 2, 2, 2 )
SELECT *
FROM #b b
OUTER APPLY ( SELECT TOP 1
a.*
FROM #ba ba
JOIN #a a ON a.AID = ba.AID
WHERE ba.BID = b.BID
ORDER BY Priority
) o
Output:
BID AID
1 1
2 1
Something like:
SELECT b.BID ,
b.DateAdded ,
b.PMonthName ,
b.PDay ,
b.Header ,
b.AddedBy ,
b.PContent ,
b.Category ,
b.Deleted ,
b.Intro ,
b.Tags ,
o.Name ,
o.Description ,
o.Location ,
o.Deleted AS Expr1 ,
o.Priority
FROM dbo.tblBlog b
OUTER APPLY ( SELECT TOP 1
a.* ,
al.Priority
FROM dbo.tblAssetLink al
JOIN dbo.tblAssets a ON al.AID = a.AID
WHERE b.BID = al.BID
ORDER BY al.Priority
) o
WHERE b.Deleted = 'False'
You cannot join three tables unless they all have the same attribute. It would work if all tables had BID, but the second join is trying to join AID. Which wont work. They all have to have BID.
Based on your comments
i would like to get is just one asset per blog post (top one ordered
by Priority)
You can change your query as following. I suggest changing the join with dbo.tblAssetLink to filtered one, which contains only one (highest priority) link for every blog.
SELECT dbo.tblBlog.BID,
dbo.tblBlog.DateAdded,
dbo.tblBlog.PMonthName,
dbo.tblBlog.PDay,
dbo.tblBlog.Header,
dbo.tblBlog.AddedBy,
dbo.tblBlog.PContent,
dbo.tblBlog.Category,
dbo.tblBlog.Deleted,
dbo.tblBlog.Intro,
dbo.tblBlog.Tags,
dbo.tblAssets.Name,
dbo.tblAssets.Description,
dbo.tblAssets.Location,
dbo.tblAssets.Deleted AS Expr1,
dbo.tblAssetLink.Priority
FROM dbo.tblBlog
LEFT OUTER JOIN
(SELECT BID, AID,
ROW_NUMBER() OVER (PARTITION BY BID ORDER BY [Priority] DESC) as N
FROM dbo.tblAssetLink) AS filteredAssetLink
ON dbo.tblBlog.BID = filteredAssetLink.BID
LEFT OUTER JOIN dbo.tblAssets
ON filteredAssetLink.AID = dbo.tblAssets.AID
WHERE dbo.tblBlog.Deleted = 'False' AND filteredAssetLink.N = 1
ORDER BY tblBlog.DateAdded DESC

How to use Alias name of inner query as a column to get record that have no data or is null in sql query?

i tried to use like this but its not giving proper result that i want
SELECT SubCategoryName,
SubCategoryId,
(SELECT TOP (1) Image
FROM PostImage
WHERE (PostDesignId LIKE (
SELECT TOP (1) PostDesignId
FROM PostDesign
WHERE (SubCategoryId = SC.SubCategoryId)
OR (SubCategoryId2 = SC.SubCategoryId)
)
)
) AS ImageName
FROM SubCategory AS SC
WHERE ImageName IS NOT NULL
Please help me....
Try this:
SELECT sq.SubCategoryName,
sq.SubCategoryId,
sq.ImageName
FROM
(
SELECT SubCategoryName,
SubCategoryId,
(SELECT TOP (1) Image
FROM PostImage
WHERE (PostDesignId LIKE (
SELECT TOP (1) PostDesignId
FROM PostDesign
WHERE (SubCategoryId = SC.SubCategoryId)
OR (SubCategoryId2 = SC.SubCategoryId)
)
)
) AS ImageName
FROM SubCategory AS SC
) as sq
WHERE sq.ImageName IS NOT NULL

Tree view using SQL Query

I have a regions table of which I want a tree view (table simple ordered as tree) is it possible using sql queries help is appreciated, I tried to do it using self joins but i did not get the desired result.
tree view is something like this
Indiv
Div1
Zon1
div2
zon2
div3
zon3
EDIT:
as per Charles Bretana suggetion I tried CTE in below query and it did not give me desired result.
WITH Emp_CTE (id, ParentID, name)
AS (
SELECT id, ParentID, name
FROM eQPortal_Region
WHERE ParentID=0
UNION ALL
SELECT e.id, e.ParentID, e.name
FROM eQPortal_Region e
INNER JOIN Emp_CTE ecte ON ecte.id = e.ParentID
)
SELECT *
FROM Emp_CTE
GO
This is the result .. what went wrong ?
InDiv1
Div1
Div2
Div3
Zon3
Zon2
zon1
This guy Maulik Dhorajia answers the question perfectly ...
http://maulikdhorajia.blogspot.com/2012/06/sql-server-using-ctecommon-table.html
Made a replica of the query ..
;WITH CTECompany
AS
(
SELECT
ID,
ParentID,
Name ,
0 AS HLevel,
CAST(RIGHT(REPLICATE('_',5) + CONVERT(VARCHAR(20),ID),20) AS VARCHAR(MAX)) AS OrderByField
FROM Region
WHERE ParentID = 0
UNION ALL
SELECT
C.ID,
C.ParentID,
C.Name ,
(CTE.HLevel + 1) AS HLevel,
CTE.OrderByField + CAST(RIGHT(REPLICATE('_',5) + CONVERT(VARCHAR(20),C.ID),20) AS VARCHAR(MAX)) AS OrderByField
FROM Region C
INNER JOIN CTECompany CTE ON CTE.ID = C.ParentID
WHERE C.ParentID IS NOT NULL
)
-- Working Example
SELECT
ID
, ParentID
, HLevel
, Name
, (REPLICATE( '----' , HLevel ) + Name) AS Hierachy
FROM CTECompany
ORDER BY OrderByField
See the following sample SQL script:
DECLARE #lV NCHAR(1)=NCHAR(9474),#lR NCHAR(1)=NCHAR(9500),#lU NCHAR(1)=NCHAR(9492),#spc NCHAR(1)=' ';
WITH data AS(SELECT * FROM(VALUES(1,'0','In Div1',1),(2,'1','Div1',1),(3,'2','zon1',1),(4,'1','Div2',2),(5,'1','Div3',3),(6,'4','Zon2',1),(7,'5','Zon3',1))t([ID],[ParentID],[Name],[SeqOrder])
),d_root AS(SELECT CAST('/'AS NVARCHAR(MAX))[n_path],* FROM data WHERE ParentID='0'
),d_cte AS(SELECT b.n_path+CAST(ROW_NUMBER()OVER(ORDER BY a.ID)AS NVARCHAR(MAX))+'/'[n_path],a.* FROM data a INNER JOIN d_root b ON a.ParentID=b.ID UNION ALL SELECT b.n_path+CAST(ROW_NUMBER()OVER(ORDER BY a.ID)AS NVARCHAR(MAX))+'/'[n_path],a.* FROM data A INNER JOIN d_cte b ON a.ParentID=b.ID
),Tree_BASE AS (SELECT CAST(n_path AS HIERARCHYID)[h_id],* FROM d_root UNION ALL SELECT CAST(n_path AS HIERARCHYID)[h_id],* FROM d_cte
),cte_o AS(SELECT a.h_id,CASE WHEN EXISTS(SELECT * FROM Tree_BASE WHERE h_id>b.h_id AND h_id.GetAncestor(1)=b.h_id.GetAncestor(1))THEN #lV ELSE #spc END[t_l] FROM Tree_BASE a INNER JOIN Tree_BASE b ON a.h_id.IsDescendantOf(b.h_id)=1 AND NOT b.h_id=HIERARCHYID::GetRoot()
),cte_m AS(SELECT x.*,(SELECT t_l+'' FROM cte_o WHERE h_id=x.h_id FOR XML PATH(''))[b_tree] FROM Tree_BASE x
),cte_h AS(SELECT ISNULL(LEFT(b_tree,LEN(b_tree)-1)+CASE WHEN EXISTS(SELECT * FROM Tree_BASE WHERE h_id>a.h_id AND h_id.GetAncestor(1)=a.h_id.GetAncestor(1))THEN #lR ELSE #lU END,'')+' '+RTRIM(Name) [TreeV],a.h_id FROM cte_m a
)SELECT b.TreeV,ROW_NUMBER()OVER(ORDER BY a.h_id ASC)[row_id]FROM Tree_BASE a INNER JOIN cte_h b ON a.h_id=b.h_id ORDER BY row_id

SQL show records that don't exist in my table variable

I have a table variable that holds orderID, UnitID and OrderServiceId (it is already populated via a query with insert statement).
I then have a query under this that returns 15 columns which also include the OrderId, UnitId, OrderServiceId
I need to only return the rows from this query where the same combination of OrderId, UnitId, and OrderServiceId are not in the table variable.
You can use NOT EXISTS. e.g.
FROM YourQuery q
WHERE NOT EXISTS
(
SELECT * FROM #TableVar t
WHERE t.OrderId = q.OrderId
and t.UnitId = q.UnitId
and t.OrderServiceId=q.OrderServiceId
)
select q.*
from (
MyQuery
) q
left outer join MyTableVariable t on q.ORDERID = t.ORDERID
and q.UNITID= t.UNITID
and q.ORDERSERVICESID = t.ORDERSERVICESID
where t.ORDERID is null
You can use EXCEPT | INTERSECT operators for this (link).
Example:
(select 3,4,1
union all
select 2,4,1)
intersect
(select 1,2,9
union all
select 3,4,1)