SQL Server: case/if else -select and apply function only if present in table - sql

I have the following dynamic query that creates a pivoted table for each account_id against the products using an UDF. I need to add spaces after the UDF is executed depending up the account_id being matched to the specific tables. This works perfectly fine, and returns the 2nd table in the image, I just want to add some condition where it checks for account id's present in other tables and then adds spaces to output from the UDF eg- the account id in the pivot matches the id present in test_rev then 2 spaces if the account_id in the pivot matches the id present in test_oncontract then 3 spaces so on
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.A_NAME)
FROM TEST_11 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(
select account_id
, dbo.make_table(apple,ball,cat,dog) AS newvalue
,a_name
from test_sample
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
execute(#query)
Image below shows how make_table udf converts the 1st table into 2nd just picking up the initials from each column name from the 1st table
I was able to call my function and add the required spaces withing the select.
But the case statement just executes the first condition and I cant get the records from the other tables. How can I implement if conditions instead of the case statements to to get data depending on all four conditions. Below is the code I am currently using:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.a_name)
FROM CRS_PRODLINE c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(select account_id,
(case
when exists (select account_id from [dbo].[TEST_R6])
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(1) + ''rr''
when exists (select account_id from tbl_noR6)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(2) + ''cc''
when exists (select account_id from tbl_acct)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(3) + ''pp''
when exists (select account_id from test_NA)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(4) + ''no''
end) as newvalue,
a_name
from CRS_PRODLINE
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
execute(#query)

Related

Summing multiple dynamically declared variables (fast)

I'm developing a program where I have multiple columns which I need to show the sum of to anEnd-user. These columns are assigned in the table ColumnTest in the column ColumnNames and their names can be changed by the user. Therefore I need to look up all the column names in ColumnTest\ColumnNames and afterwards sum all values regarding these columnnames from the outputtable.
I have previously used this script where I get all the columnnames in #cols like this [col1].[col2].[col3] and so on, but when I try to run the query I'm not able to sum these columns using '+ #cols + '. When I run this I get the following error: The SUM function requires 1 argument(s). Is there a viable option to do this procedure, without compromising the loading-time substantially?
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.ColumnNames)
FROM ColumnTest c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query =
'
SELECT
ID
,SUM('+ #cols + ')
FROM Output_table
GROUP BY
ID
'
execute(#query);
Try this,
DECLARE
#cols AS NVARCHAR(MAX)='',
#query AS NVARCHAR(MAX);
SELECT #cols += 'SUM('+ColumnNames+') as ['+ColumnNames+'],'
from
(
SELECT distinct ColumnNames FROM ColumnTest
)A
SELECT #cols=LEFT(#cols,LEN(#cols)-1)
set #query =
'
SELECT ID,'+ #cols + '
FROM Output_table
GROUP BY ID
'
execute(#query);
or if you want addition of all column values you can use below query
DECLARE #cols AS NVARCHAR(MAX)='',
#query AS NVARCHAR(MAX);
SELECT #cols += ''+ColumnNames+'+'
FROM
(
SELECT DISTINCT ColumnNames FROM ColumnTest
)A
SELECT #cols=LEFT(#cols,LEN(#cols)-1)
set #query =
'
SELECT ID,SUM('+ #cols + ')
FROM Output_table
GROUP BY ID
'
execute(#query);
You can not use comma separated like ','
You can use '+'
Try this
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct '+' + QUOTENAME(c.ColumnNames)
FROM ColumnTest c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query =
'
SELECT
ID
,SUM('+ #cols + ')
FROM Output_table
GROUP BY
ID
'
execute(#query);

How to display columns as rows in a SQL query?

I'm trying to display exam results form simple database containing two tables tblStudents and tblExamResults.
tblstudents contains student ID and Full_Name columns
In tblexamResults columns are Student_id, Subject and Marks.
as in below Picture
1- Currently I am displaying Student results using this query
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
order by tblStudents.Full_Name
2 - And results looks like in the following picture:
3 - But what I want is to display each subject as row and get result of each subject below it
So that each student's result is displayed in the same row:
Student_Name sub1_result sub2_Result sub3_Result
Like in the following picture (Excel screenshot)
So:
How I can display data in that format?
Is that possible in SQL Server?
select fullname,[english] english, [history] history, [physics] physics
from
(
select fullname,subject,marks
from (yourquery)
) src
pivot
(
max(marks)
for subject in ([english], [history], [physics])
) piv;
or
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM (yourquery) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT fullname, ' + #cols + ' from
(
select fullname,subject,marks
from (your query)
) x
pivot
(
max(marks)
for subject in (' + #cols + ')
) p '
execute(#query)
fullname english history physics
a 85 70 60
i 60 100 89
s 90 90 99
Finally I've used next part of #Chanukya Answer with little Changes
in that Answer i was getting error at line 5 becouse of parentheses in FROM (yourquery) c
Declare #query nvarchar(max);
DECLARE #cols AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM tblExamResults c ' parentheses Removed from (tblExamResults) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
print(#cols)
set #query = '
SELECT *
FROM (
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
) as s
PIVOT
(
sum(marks) FOR subject IN ('+ #cols +')
)AS pvt'
;
execute(#query)

How to to select two columns (Name, Value) and return as single result?

So I have a table that has a column for Name, and a column for Value and an ID. There can be multiple rows for the same ID. I would like to create a select that will return a single row for each ID and the values in the Name column would be the column name, and the Value would be the value. Example:
CREATE TABLE dbo.Attribute
(
AttributeID int NOT NULL,
Name varchar(20) NOT NULL,
Value varchar(20) NOT NULL
) ;
Data:
{1,"Color", "Blue"},{1,"Material", "leather"}
Would like Select to return:
[AttributeID:1, Color:Blue, Material: leather]
I have been playing with PIVOT and UNPIVOT but not getting what I need.
Thanks to #Mihai's link. I was able to do what I
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Name)
FROM VariantAttribute c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT variantid, ' + #cols + ' from
(
select variantid
, Name
, value
from VariantAttribute
) x
pivot
(
max([Value])
for Name in (' + #cols + ')
) p '
execute(#query)
Before I get more slack about how I am storing this data. There is not a way out of it at the moment, but this query is to push this data to Azure Search (uses Elastic search) to be able to easily search on this data.

Dynamic variable store results in temp table and variable error

I have a dynamic PIVOT that partially works. It works when I don't request a where clause using a variable but just use a specific number.
I also want to be able to store the results into a temp table.
Is it possible to have a where clause variable in a dynamic pivot and is it possible to save the results to a temp table?
Here is my current query that is not working
declare #CourseID int = 2
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(UnitID)
FROM LMS_Unit_Status where CourseID = #CourseID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT LearnerID, ' + #cols + ' from
(select LearnerID,UnitID,Completed from LMS_Unit_Status where CourseID = #CourseID) as s
pivot
(
min(Completed)
for UnitID in (' + #cols + ')
) p'
execute(#query);
Msg 137, Level 15, State 2, Line 2
Must declare the scalar variable "#CourseID".
Thanks
If #CurseID is a variable parser should know it is a variable and not a string
And since you have no idea how many columns table will have you can simply use select into statement.
set #query = 'SELECT LearnerID, ' + #cols + ' into tempTable from
(select LearnerID,UnitID,Completed from LMS_Unit_Status where CourseID = ' + #CourseID + ') as s
pivot
(
min(Completed)
for UnitID in (' + #cols + ')
) p
select * from tempTable
drop table tempTable'
execute(#query);
Cheers!

while converting column to row not able to fetch value from another table automatically

select *
from (
select vtid, convert(date, dtime) as Date from Transaction_tbl where locid = 5
) as vt
pivot (
count(vtid)
for vtid in (select vtid from VType_tbl)
) as pvt
while executing this query am getting error
Incorrect syntax near the keyword 'select'." and Incorrect syntax near
')'.
actually I have one more table,name= Vtype_table , How Can I load all vtid from vtype table in this query? I want to get output depend upon vtid.
Any help greatly appreciated.
Your PIVOT syntax is correct except you are using a SELECT statement inside your PIVOT.
You cannot use a SELECT statement inside the PIVOT IN clause to select column headers. It is required that the columns for the IN clause be known prior to executing the query.
If you are looking to generate a dynamic list of vtid values, then you will need to use dynamic SQL to get the result and the syntax will be similar to the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vtid)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select vtid, convert(date, dtime) as Date
from Transaction_tbl
where locid = 5
) d
pivot
(
count(vtid)
for vtid in (' + #cols + ')
) p '
execute(#query);
Edit, if you want the type names to appear then you should be able to use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vt_name)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select v.vt_name, convert(date, dtime) as Date
from Transaction_tbl t
inner join VType_tbl v
on t.vtid = v.vtid
where locid = 5
) d
pivot
(
count(vt_name)
for vt_name in (' + #cols + ')
) p '
execute(#query)
Note: I am guessing on the column name for VType_tbl