Create view with with statement - sql

How to create view with a with statement?
I'm getting on error on it:
WITH temp as (
select uu.email, u.logintime, u.region, p.id as panelid, p.panelname, p.numberofdownloads, dimensionType + ' (' + dimensionValue + ')' as filter
from stat_users u
left join stat_panels p
on u.id=p.sessionid
left join stat_filters f
on p.id=f.panelid
left join users uu
on uu.id=u.userid
where uu.Organization = 'name' AND
year(logintime) between 2015 and 2017
and panelname is not null
)
CREATE VIEW final as(
select aa.email, aa.logintime, aa.region, aa.panelname, aa.numberofdownloads as downloads, case when len(aa.filters) > 0 then left(aa.filters, len(aa.filters)-1) else '' end as filters
from (
Select distinct a.email, a.logintime, a.region, a.panelname, a.numberofdownloads,
(
Select b.filter + ', ' AS [text()]
From temp b
Where b.panelid=a.panelid
ORDER BY b.panelid
For XML PATH ('')
) filters
from temp a
) aa
)
I'm getting such error :
> Incorrect syntax near the keyword 'CREATE'. 'CREATE VIEW' must be the
> first statement in a query batch.
So, I need just to use Create view using select which based on WITH statement on Sql server 2014

Yes always the CREATE has to be the first statement in a query batch
CREATE VIEW vFinal AS
WITH Temp AS (
SELECT uu.email, u.logintime, u.region, p.id AS panelid, p.panelname, p.numberofdownloads, dimensionType + ' (' + dimensionValue + ')' AS Filter
FROM stat_users u
LEFT JOIN stat_panels p ON u.id=p.sessionid
LEFT JOIN stat_filters f ON p.id=f.panelid
LEFT JOIN users uu ON uu.id=u.userid
WHERE uu.Organization = 'name' AND
YEAR(logintime) BETWEEN 2015 AND 2017
AND panelname IS NOT NULL
)
SELECT aa.email, aa.logintime, aa.region, aa.panelname, aa.numberofdownloads AS downloads, CASE WHEN LEN(aa.filters) > 0 THEN LEFT(aa.filters, LEN(aa.filters)-1) else '' end as filters
FROM (
SELECT DISTINCT a.email, a.logintime, a.region, a.panelname, a.numberofdownloads,
(
SELECT b.filter + ', ' AS [text()]
FROM temp b
WHERE b.panelid=a.panelid
ORDER BY b.panelid
FOR XML PATH ('')
) filters
FROM temp a
) aa
GO
Syntax to create a view table using CTE
CREATE VIEW View_Name AS
WITH CTE_Name (Columns) AS (SELECT QUERY)
SELECT QUERY using the CTE Table
GO

The with clause is an optional prefix for select:
WITH query_name (column_name1, ...) AS
(SELECT ...)
SELECT ...
This is also true when with is used in a view:
CREATE VIEW ...
WITH ...
SELECT ...
;
See also: http://modern-sql.com/feature/with

CREATE or replace VIEW final as
select aa.email, aa.logintime, aa.region, aa.panelname, aa.numberofdownloads as downloads, case when len(aa.filters) > 0 then left(aa.filters, len(aa.filters)-1) else '' end as filters
from (
Select distinct a.email, a.logintime, a.region, a.panelname, a.numberofdownloads,
(
Select b.filter + ', ' AS [text()]
From temp b
Where b.panelid=a.panelid
ORDER BY b.panelid
For XML PATH ('')
) filters
from temp a )

Related

SQL: how to use loop in PIVOT

My SQL is:
SELECT * FROM
(SELECT
cmdoc.documentno 'DRG. NO.',
cmdoc.subject 'TITLE',
CAST(documentno AS VARCHAR(255)) AS docno,
CAST(cmrev.code AS VARCHAR(255)) AS code
FROM cmdocument cmdoc
INNER JOIN cmdocumentrevision cmrev
ON cmdoc.cmdocument = cmrev.cmdocument
INNER JOIN cmdocumentdefn
ON cmdoc.cmdocumentdefn = cmdocumentdefn.cmdocumentdefn
WHERE
cmdocumentdefn.isrevisable = 1
) x
PIVOT(COUNT(docno) FOR code IN([A],[B],[C],[D],[E],[F],[G])) pvt
I want to loop the line inside IN('/* here */').
If possible, I want the start and end to be an SQL like:
-- start
SELECT MIN(code) FROM table
-- end
SELECT MAX(code) FROM table
how can I do it?

Optimize query using Concat method

I have a query which uses join, then group by caseId and then a concat-like function using STUFF.
SELECT distinct [CaseID], STUFF((SELECT ';' +space(1)+ A.[AssignedPathologist]+' ' FROM CTE1 A
WHERE A.[CaseID]=B.[CaseID] FOR XML PATH('')),1,1,'') As [AssignedPathologist]
From CTE1 B
Group By [CaseID]
The problem is that this query is super, super-slow and I tried to optimize it using CONCAT instead.
SELECT distinct A.[CaseID], [AssignedPathologist] = CASE A.AssignedPathologist = B.AssignedPathologist
WHEN 1 THEN A.AssignedPathologist
ELSE CONCAT(A.AssignedPathologist, ' ', B.AssignedPathologist)
END
FROM CTE1 A
INNER JOIN CTE1 B ON A.[CaseID]=B.[CaseID]
END
but it gives me syntax error here
[AssignedPathologist] = CASE A.AssignedPathologist = B.AssignedPathologist
which is logic because I used twice = here.
Is there any method to optimize my query using CONCAT or another methods ?
Thank you
I would try with this :
SELECT [CaseID],
STUFF( (SELECT CONCAT('; ', A.[AssignedPathologist])
FROM CTE1 A
WHERE A.[CaseID] = B.[CaseID]
FOR XML PATH('')
),1, 1, ''
) As [AssignedPathologist]
FROM (SELECT DISTINCT CaseID CTE1 B) B;
For newer versions you can use string_agg() :
SELECT CASEID, STRING_AGG(AssignedPathologist, '; ') AS AssignedPathologist
FROM CTE1 C1
GROUP BY CASEID;

Update statement SQL with CTE

I have a common table expression that I am using trying to use as an update statement. The only reason for the CTE is so I can use a where clause to filter by CredCount. I would like to use that where clause to update only records that match in this case CredCount of 2. However, I am having trouble with the update part of the query.
Members_id
Credentials
CredCount
members_amountdue
1
CMA, CPR
2
0
2
CMA, CPR
2
0
3
CMA, CPR
2
0
Here is the query for that
WITH CTE AS (
SELECT members_id, members_amountdue, [Credentials], LEN([Credentials]) - LEN(REPLACE([Credentials], ',', '')) + 1 AS CredCount
FROM (
SELECT DISTINCT mem1.members_id, mem1.members_amountdue,
STUFF(
(SELECT DISTINCT ', ' + credentials_code
FROM members AS mem JOIN
members_credentials AS mc ON mc.members_id = mem.members_id JOIN
credentials AS c ON c.credentials_id = mc.credentials_id
WHERE mem.[members_id] = mem1.[members_id]
FOR XML PATH ('')), 1, 1, '') AS [Credentials]
FROM members AS mem1 JOIN
members_status as ms on ms.members_status_id = mem1.members_status_id
) AS derived),
CTE2 AS ( SELECT members_id
FROM members)
SELECT CTE.members_id, CTE.Credentials, CTE.CredCount, (CTE.members_amountdue + 25) as NewPriceTotal
FROM CTE JOIN
CTE2 ON CTE.members_id = CTE2.members_id
WHERE CTE.CredCount = 2
With the update statement I was looking at an example provided here at Update records in table from CTE so I added the update statement to the bottom of the query
WITH CTE AS (
SELECT members_id, members_amountdue, [Credentials], LEN([Credentials]) - LEN(REPLACE([Credentials], ',', '')) + 1 AS CredCount
FROM (
SELECT DISTINCT mem1.members_id, mem1.members_amountdue,
STUFF(
(SELECT DISTINCT ', ' + credentials_code
FROM members AS mem JOIN
members_credentials AS mc ON mc.members_id = mem.members_id JOIN
credentials AS c ON c.credentials_id = mc.credentials_id
WHERE mem.[members_id] = mem1.[members_id]
FOR XML PATH ('')), 1, 1, '') AS [Credentials]
FROM members AS mem1 JOIN
members_status as ms on ms.members_status_id = mem1.members_status_id
) AS derived),
CTE2 AS ( SELECT members_id
FROM members)
SELECT CTE.members_id, CTE.Credentials, CTE.CredCount, (CTE.members_amountdue + 25) as NewPriceTotal
FROM CTE JOIN
CTE2 ON CTE.members_id = CTE2.members_id
WHERE CTE.CredCount = 2
UPDATE members
set members_amountdue = NewPriceTotal
When I add the update statement I get an error for invalid column name for 'NewPriceTotal'. I know I need the column to match in order for the update to work but I'm not sure why it's invalid.
Members_id
Credentials
CredCount
NewPriceTotal
1
CMA, CPR
2
25
2
CMA, CPR
2
25
3
CMA, CPR
2
25
I would like for the NewPriceTotal to be set at the members_amountdue from the members table but I'm not sure where I made the wrong turn at. Any help, comments or feedback is greatly appreciated.
Try this:
....
CTE2 AS (
SELECT members_id
FROM members
), CTE3 AS (
SELECT CTE.members_id, CTE.Credentials, CTE.CredCount,
CTE.members_amountdue,
(CTE.members_amountdue + 25) as NewPriceTotal
FROM CTE JOIN CTE2 ON CTE.members_id = CTE2.members_id
WHERE CTE.CredCount = 2)
UPDATE CTE3
SET members_amountdue = NewPriceTotal

trying to concatenate a column into a comma delimited list

i have 3 tables, 1 for products and one for categories the products are assigned to. what IM trying to do is concatenate the column called stCategoryName to a single column in a comma delimited list.
Basically I have the products table containing the primary key for each product and im trying to figure out how to concatenate all the stcategoryName column next to each product so i can have a simplified return
what im trying to get is the following.
stProductID stCategoryName
123 category1,category2,category3
SELECT
dbo.StoreItemTracking.StCategoryID,
dbo.StoreItemTracking.StProductID,
dbo.StoreItemTracking.viewOrder,
dbo.StoreCategories.StCategoryName,
dbo.Store_Products.PartNumber
FROM
dbo.StoreItemTracking
INNER JOIN dbo.StoreCategories
ON dbo.StoreItemTracking.StCategoryID = dbo.StoreCategories.StCategoryID
INNER JOIN dbo.Store_Products
ON dbo.StoreItemTracking.StProductID = dbo.Store_Products.ID
Im stuck as to how to concatenate a column where the query contains 3 tables to select from.
any help greatly appreciated
Look at using coalesce to turn category into a CSV:
See example:
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '')
+ CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
You can also use CTE's or Subqueries. See:
http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=createacommadelimitedlist
Another nice and easy example:
http://www.codeproject.com/Articles/21082/Concatenate-Field-Values-in-One-String-Using-CTE-i
This:
FId FName
--- ----
2 A
4 B
5 C
6 D
8 E
with:
;WITH ABC (FId, FName) AS
(
SELECT 1, CAST('' AS VARCHAR(8000))
UNION ALL
SELECT B.FId + 1, B.FName + A.FName + ', '
FROM (And the above query will return
SELECT Row_Number() OVER (ORDER BY FId) AS RN, FName FROM tblTest) A
INNER JOIN ABC B ON A.RN = B.FId
)
SELECT TOP 1 FName FROM ABC ORDER BY FId DESC
becomes:
FName
----------------------------
A, B, C, D, E,
Don't understand how your products and categories are connected but in general I do like this to create comma separated lists.
SELECT table1.Id
,Csv
FROM table1
CROSS APPLY (
-- Double select so we can have an alias for the csv column
SELECT (SELECT ',' + table2.Name
FROM table2
WHERE table2.Id = table1.Id
FOR XML PATH('')
) AS RawCsv
) AS CA1
CROSS APPLY (
-- Trim the first comma
SELECT RIGHT(RawCsv, LEN(RawCsv) - 1) AS Csv
) AS CA2

Why does this NOT IN query work as intended, but not this NOT EXISTS query?

Working (NOT IN) retrieves 3 rows:
select DISTINCT d.* from Device d , Company c3
WHERE d.deviceid NOT IN
(
Select d1.deviceid from Device d1, Clone x1
WHERE d1.deviceid = x1.deviceID
AND
(
x1.XPath = 'hi'
OR x1.XPath = 'bye'
)
AND
(
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('T130SF0W2050', ',')) as s
WHERE x1.Value like '%' + s.items + '%' )
)
)
AND
d.companyid = c3.companyid and c3.companynumber in (SELECT * FROM [dbo].[Split] ('00223200', ','))
Not Working(not exists):
select DISTINCT d.* from Device d , Company c3
WHERE NOT EXISTS
(Select * from Device d1, Clone x1
WHERE d1.deviceid = x1.deviceID
AND
(
x1.XPath = 'hi'
OR x1.XPath = 'bye'
)
AND
(
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('T130SF0W2050', ',')) as s
WHERE x1.Value like '%' + s.items + '%' )
)
)
AND
d.companyid = c3.companyid and c3.companynumber in (SELECT * FROM [dbo].[Split] ('00223200', ','))
I'm unsure I'm using the exists syntax correct, what should I select from the subquery? I've tried a few different combinations. It won't run if I put WHERE d.deviceid NOT EXISTS
Solution (thanks to Nikola):
add AND d1.deviceid = d.deviceid inside the Exists subquery.
The difference is that the NOT IN query returns devices that match the company and don't match the inner query specification.
For the NOT EXIST query to work as written (where "work as written" refers to returning the same result as the top query), there can't be any devices that exist matching the inner query. If any devices match the inner query at all, the query won't return any results.