IF value is in list set value in next column NULL - sql

I have a huge SQL table and need to filter several columns (called Field) if they are in this list:
AAA, BBB, CCC, DDD, EEE
If this is the case, set respective value column to NULL.
Let me give you an example table:
Field1 Value1 Field2 Value2 ...... Field10 Value10
AAA 9A AAA 9A CCC World
BBB 1 KKK 0
ZZZ 9 AAA 9A CCC 42
CCC 7
LLL 9 AAA 3 III 98
KKK 3 AAA 4
DDD 100 AAA Hello CCC 6
Not all Field Value combinations are filled up until Value10. However every column that is named FieldXX must be checked for the list entries. If a cell is equal to a list entry the respective value field should be set NULL. Otherwise the value field remains untouched.
I struggle to figure out the correct CASE statement for this specific issue. I tried the following code:
SELECT CAST(
CASE
WHEN Field* = AAA or BBB or CCC or DDD or EEE
THEN Value* = 0
ELSE Value* = Value*
END AS bit)
FROM dbo.Log
But this query totally fails and it might not be for specific field-value pairs.
Expected Output
Field1 Value1 Field2 Value2 ...... Field10 Value10
AAA 0 AAA 0 CCC 0
BBB 0 KKK 0
ZZZ 9 AAA 0 CCC 0
CCC 0
LLL 9 AAA 0 III 98
KKK 3 AAA 0
DDD 0 AAA 0 CCC 0
Table name is dbo.Log.

If I understood correctly, you are trying to update ValueX columns based on FieldX data.
In that case you need to write Case condition for every column.
You can directly write 10 Case conditions like below
UPDATE A_LOG
SET VALUE1 = CASE WHEN FIELD1 IN ('AAA','BBB','CCC','DDD','EEE' ) THEN 0 ELSE VALUE1 END,
VALUE2 = CASE WHEN FIELD2 IN ('AAA','BBB','CCC','DDD','EEE' ) THEN 0 ELSE VALUE2 END,
VALUE3 = CASE WHEN FIELD3 IN ('AAA','BBB','CCC','DDD','EEE' ) THEN 0 ELSE VALUE3 END
.
.
VALUE10 = CASE WHEN FIELD10 IN ('AAA','BBB','CCC','DDD','EEE' ) THEN 0 ELSE VALUE10 END
Or you can generate Update statement with Dynamic query like below
DECLARE #IN VARCHAR(100)=' IN (''AAA'',''BBB'',''CCC'',''DDD'',''EEE'' )'
, #SQL VARCHAR(MAX) = 'UPDATE A_LOG SET '
SELECT #SQL = #SQL+ VAL FROM
(
SELECT COLUMN_NAME + ' = CASE WHEN FIELD'+ REPLACE(COLUMN_NAME,'VALUE','')
+ #IN+ ' THEN 0 ELSE '+ COLUMN_NAME + ' END,
' VAL
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'LOG'
AND COLUMN_NAME LIKE 'VALUE%'
)A
SELECT #SQL = SUBSTRING(#SQL,1,LEN(#SQL)-3)
SELECT #SQL
That will give you update statement for every column with a case condition.

I'm pretty certain the wildcard you're trying to use for your CASE WHEN isn't a valid way of using it.
You can use variables to create a SQL string that you can then copy and execute - this way, if you need to increase the number of fields you're checking, you only have to change one part of your code :)
The code below creates the SQL string then prints it out in the console window:
DECLARE #cnt INT = 1;
DECLARE #sql VARCHAR(MAX) = 'SELECT ';
WHILE #cnt <= 10
BEGIN
DECLARE #COLUMN VARCHAR(MAX) = 'Field' + CAST(#cnt AS varchar(max))
DECLARE #VALUE VARCHAR(MAX) = 'Value' + CAST(#cnt AS varchar(max))
SET #sql = #sql + #COLUMN + ', CASE WHEN ' + #COLUMN + '= ''AAA'' OR ' + #COLUMN + '= ''BBB'' OR ' + #COLUMN + '= ''CCC'' OR ' + #COLUMN + '= ''DDD'' OR ' + #COLUMN + '= ''EEE'' THEN 0 ELSE ' + #VALUE + ' END AS ' + #VALUE;
IF #cnt != 10
(SELECT #sql = #sql + ',')
SET #cnt = #cnt +1
END
SET #sql = #sql + ' INTO [dbo].[LogFilter] FROM [dbo].[Log]';
PRINT #sql;
This code below is what is printed out (I have styled it so you can easily read it and truncated it so it doesn't take up the whole screen) :)
SELECT
Field1,
CASE WHEN Field1= 'AAA' OR Field1= 'BBB' OR Field1= 'CCC' OR Field1= 'DDD' OR Field1= 'EEE'
THEN 0 ELSE Value1 END AS Value1,
Field2,
CASE WHEN Field2= 'AAA' OR Field2= 'BBB' OR Field2= 'CCC' OR Field2= 'DDD' OR Field2= 'EEE'
THEN 0 ELSE Value2 END AS Value2,
Field3,
CASE WHEN Field3= 'AAA' OR Field3= 'BBB' OR Field3= 'CCC' OR Field3= 'DDD' OR Field3= 'EEE'
THEN 0 ELSE Value3 END AS Value3,
...
INTO [dbo].[LogFilter] FROM [dbo].[Log]
This SELECT INTO statement above places your filtered information into a brand new table :)

Try this:
Declare #Table Table(Field1 varchar(10), Value1 varchar(10), Field2 varchar(10), Value2 varchar(10) ,Field10 varchar(10) , Value10 varchar(10))
Declare #NewTable Table(Field1 varchar(10), Value1 varchar(10), Field2 varchar(10), Value2 varchar(10) ,Field10 varchar(10) , Value10 varchar(10))
insert into #Table
SELECT 'AAA','9A','AAA','9A','CCC','World' Union All
SELECT 'BBB','1','KKK','0',NULL,NULL Union All
SELECT 'ZZZ','9','AAA','9A','CCC','42' Union All
SELECT 'CCC','7',NULL,NULL,NULL,NULL Union All
SELECT 'LLL','9','AAA','3','III','98' Union All
SELECT 'KKK','3','AAA','4',NULL,NULL Union All
SELECT 'DDD','100','AAA','Hello','CCC','6'
INSERT into #NewTable
Select Field1,CASE WHEN Field1 in ('AAA','BBB','CCC','DDD','EEE') THEN 0 else Value1 end As Value1
,Field2,CASE WHEN Field2 in ('AAA','BBB','CCC','DDD','EEE') THEN 0 else Value2 end As Value2
,Field10,CASE WHEN Field10 in ('AAA','BBB','CCC','DDD','EEE') THEN 0 else Value10 end As Value10
from #Table
Select * from #NewTable

The Case statement wouldn't work in the way that you've written. You need to individually compare the values in each Field and set the value of 'Value' column.
SELECT CAST(
CASE
WHEN Field1 = AAA or BBB or CCC or DDD or EEE
THEN Value1 = 0
ELSE Value1
END AS bit) Value1,
CAST(
CASE
WHEN Field2 = AAA or BBB or CCC or DDD or EEE
THEN Value2 = 0
ELSE Value2
END AS bit) Value2,
.
.
.
.
<need to write separate case statement for each column which is to be compared>
FROM dbo.Log

Related

How to select records from a table when a condition of another table is satisfied

I have this query that runs regularly.
SELECT REPLICATE('0', 10-LEN(PolicyNumber)) + PolicyNumber AS PolicyNumber,
REPLICATE('0', 7-LEN(BOCBranch)) + BOCBranch AS BOCBranch,
CIFNumber+ REPLICATE(' ', 8-LEN(CIFNumber)) AS CIFNumber,
REPLICATE('0', 7-LEN(EmployeeNumber)) + EmployeeNumber AS EmployeeNumber,
PremiumSign,
REPLACE(REPLICATE('0',16-LEN(CAST(Premium AS VARCHAR))) + CAST(Premium AS VARCHAR),'.','') AS Premium,
CASE WHEN RegistrationDate IS NULL
THEN REPLICATE(' ', 8)
ELSE REPLACE(CONVERT(VARCHAR(10),RegistrationDate,103),'/','')
END AS RegistrationDate,
ActivityCode + REPLICATE(' ', 10-LEN(ActivityCode)) AS ActivityCode,
ActivityDescription + REPLICATE(' ', 255-LEN(ActivityDescription)) AS ActivityDescription,
PolicyTypeCode + REPLICATE(' ', 10-LEN(PolicyTypeCode)) AS PolicyTypeCode,
PolicyTypeDescription + REPLICATE(' ', 255-LEN(PolicyTypeDescription)) AS PolicyTypeDescription,
ContributionCode + REPLICATE(' ', 10-LEN(ContributionCode)) AS ContributionCode,
ContributionDescription + REPLICATE(' ', 255-LEN(ContributionDescription)) AS ContributionDescription,
ActivityMilimetra + REPLICATE(' ', 1-LEN(ActivityMilimetra)) AS ActivityMilimetra,
REPLICATE('0', 8-LEN(SourceCode)) + CAST(SourceCode AS varCHAR) AS SourceCode
FROM FileExtraction.EXTR_MILIMETRA
ORDER BY PolicyNumber
I have created a new table called FIELD_ACTIVATIONS as per managerial instructions like so:
FieldName CategoryID IsActive
-------------------------------------------------- ----------- --------
PolicyNumber 1 1
BOCBranch 1 1
CIFNumber 1 1
EmployeeNumber 1 0
PremiumSign 1 0
RegistrationDate 1 0
ActivityCode 1 0
ActivityDescription 1 0
PolicyTypeCode 1 0
PolicyTypeDescription 1 0
ContributionCode 1 0
ContributionDescription 1 0
ActivityMilimetra 1 0
SourceCode 1 0
Premium 1 0
PolicyNumber 2 0
BOCBranch 2 0
CIFNumber 2 0
EmployeeNumber 2 1
PremiumSign 2 1
RegistrationDate 2 1
ActivityCode 2 0
ActivityDescription 2 0
PolicyTypeCode 2 0
PolicyTypeDescription 2 0
ContributionCode 2 0
ContributionDescription 2 0
ActivityMilimetra 2 0
SourceCode 2 0
Premium 2 0
PolicyNumber 3 0
BOCBranch 3 0
CIFNumber 3 0
EmployeeNumber 3 0
PremiumSign 3 0
RegistrationDate 3 0
ActivityCode 3 1
ActivityDescription 3 1
PolicyTypeCode 3 1
PolicyTypeDescription 3 0
ContributionCode 3 0
ContributionDescription 3 0
ActivityMilimetra 3 0
SourceCode 3 0
Premium 3 0
PolicyNumber 4 0
BOCBranch 4 0
CIFNumber 4 0
EmployeeNumber 4 0
PremiumSign 4 0
RegistrationDate 4 0
ActivityCode 4 0
ActivityDescription 4 0
PolicyTypeCode 4 0
PolicyTypeDescription 4 1
ContributionCode 4 1
ContributionDescription 4 1
ActivityMilimetra 4 1
SourceCode 4 1
Premium 4 1
As you may notice, each column in the SELECT statement, is a FieldName in the table.
What I need to do is to run that SELECT statement only for the columns that appear in FieldName that have a status of IsActive = 1. For the columns in the SELECT query that have a status of IsActive = 0, I would still like to select the column, but display it as an empty column.
This is all without permanently deleting or altering anything from any tables.
I've tried using Cases, Subqueries, IFs and I cannot seem to come up with a solution that will not require future alteration if any details in the FIELD_ACTIVATIONS table change.
I've also looked at this link Select records in on table based on conditions from another table? but this link presumes that there is a common field in both tables.
The main table named as "EXTR_MILIMETRA" displayed in the SELECT query has nothing in common with FIELD_ACTIVATION apart from the column name and the field name.
Here is a sample of the columns in "EXTR_MILIMETRA". (Not all columns are being shown because of limited screen space.) Each column show below is a FieldName is the table above.
By asking this I'm risking being blocked due to consecutive previous downvotes. If any extra information is needed please let me know first instead of downvoting. If that's ok. I've really tried to describe my problem well enough.
Happy to make any clarifications.
How you would write that depends on if you need performance or not. If you don't have too many rows then you can do it like:
WITH active AS
(
SELECT FieldName
FROM Field_Activations
WHERE CategoryId=1 AND IsActive=1
)
SELECT
CASE WHEN EXISTS (SELECT * FROM active WHERE FieldName='PolicyNumber')
THEN REPLICATE('0', 10-LEN(PolicyNumber)) + PolicyNumber
ELSE '' END AS PolicyNumber,
CASE WHEN EXISTS (SELECT * FROM active WHERE FieldName='BOCBranch')
then REPLICATE('0', 7-LEN(BOCBranch)) + BOCBranch
ELSE '' end AS BOCBranch,
--...
FROM FileExtraction.EXTR_MILIMETRA
ORDER BY PolicyNumber;
If you need some performance then you can write the above query as a dynamic query with a series of if and execute:
DECLARE #SQLString nvarchar(4000);
declare #active table (FieldName varchar(100));
insert into #active (FieldName)
SELECT FieldName
FROM Field_Activations
WHERE CategoryId=1 AND IsActive=1;
SET #SQLString = N'
SELECT ' +
CASE when EXISTS
(SELECT * FROM #active WHERE FieldName = 'PolicyNumber')
THEN 'REPLICATE(''0'', 10-LEN(PolicyNumber)) + PolicyNumber'
ELSE '''''' END + ' AS PolicyNumber,' +
CASE WHEN EXISTS
(SELECT * FROM #active WHERE FieldName = 'BOCBranch')
THEN 'REPLICATE(''0'', 7-LEN(BOCBranch)) + BOCBranch'
ELSE '''''' end + ' AS BOCBranch,' +
--... +
' FROM FileExtraction.EXTR_MILIMETRA
ORDER BY PolicyNumber;'
print #SQLString
EXECUTE sp_executesql #SQLString;
#NikosV you need is a dynamic query. I have called it #DynamicQuery and a method to assign those columns that you are intersted in hiding will have NULL added to them, rendering their output to be blanks. Have a look at this mock up, just change the TABLENAME to the actual name of the table you want to pull the data from and use the actual FIELD_ACTIVATIONS table you said you creatd.
DECLARE #FIELD_ACTIVATIONS TABLE (FieldName varchar(200), CategoryID int, IsActive bit)
INSERT INTO #FIELD_ACTIVATIONS
SELECT 'PolicyNumber', 1, 1 UNION ALL
SELECT 'BOCBranch', 1, 1 UNION ALL
SELECT 'CIFNumber', 1, 1 UNION ALL
SELECT 'EmployeeNumber', 1, 0 UNION ALL
SELECT 'PremiumSign', 1, 0 UNION ALL
SELECT 'RegistrationDate', 1, 0 UNION ALL
SELECT 'ActivityCode', 1, 0 UNION ALL
SELECT 'ActivityDescription', 1, 0 UNION ALL
SELECT 'PolicyTypeCode', 1, 0 UNION ALL
SELECT 'PolicyTypeDescription', 1, 0 UNION ALL
SELECT 'ContributionCode', 1, 0
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += FieldName+','
FROM (SELECT p.FieldName+''+CASE WHEN IsActive=0 THEN '=NULL' ELSE '' END FieldName
FROM #FIELD_ACTIVATIONS p
) AS x;
DECLARE #Querycolumns VARCHAR(MAX)=(select left (#columns, Len ( #columns) - 1 ))
DECLARE #Dynamicquery NVARCHAR(MAX) = '
SELECT '+ #Querycolumns +'
FROM
TABLENAME
'
The output query will be run like this :
SELECT PolicyNumber,BOCBranch,CIFNumber,EmployeeNumber=NULL,PremiumSign=NULL,RegistrationDate=NULL,ActivityCode=NULL,ActivityDescription=NULL,PolicyTypeCode=NULL,PolicyTypeDescription=NULL,ContributionCode=NULL
FROM
TABLENAME

Count in SQL statement

I have a table with the following data:
Comp ID Name Type
-----------------------
AAA D2222 Jon BR11
AAA D2222 Jon BR12
AAA D2865 Toe BR11
BBB D4151 Sue BR11
BBB D4151 Sue BR12
BBB D4151 Sue BR13
CCC D6080 Pete BR14
CCC D6723 Tom BR13
I want to write my SQL statement and display like table below
Comp BR11 BR12 BR13 BR14
---------------------------
AAA 2 1
BBB 1 1 1
CCC 1 1
But I only know to select for one Type, how can I do it for many Types ?
select
Comp, count(Type) as BR11
from
CCDL
where
Type = 'BR11'
group by
Comp
Thanks much !
Dynamic pivot is the best approach:
create table test (Comp varchar(3), ID varchar(10), Name varchar(10), Type varchar(10))
insert into test values ('AAA','D2222','Jon','BR11');
insert into test values ('AAA','D2222','Jon','BR12');
insert into test values ('AAA','D2865','Toe','BR11');
insert into test values ('BBB','D4151','Sue','BR11');
insert into test values ('BBB','D4151','Sue','BR12');
insert into test values ('BBB','D4151','Sue','BR13');
insert into test values ('CCC','D6080','Pete','BR14');
insert into test values ('CCC','D6723','Tom','BR13');
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Type)
FROM test c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Comp, ' + #cols + ' from
(
select Comp
, ID
, Type
from test
) x
pivot
(
count(ID)
for Type in (' + #cols + ')
) p '
execute(#query)
The result is
Comp BR11 BR12 BR13 BR14
AAA 2 1 0 0
BBB 1 1 1 0
CCC 0 0 1 1
You can use selective aggregates for this:
SELECT Comp
, COUNT(CASE WHEN type = 'BR11' THEN 1 END) br11
, COUNT(CASE WHEN type = 'BR12' THEN 1 END) br12
, ...
FROM CCDL
GROUP BY Comp
More about this: http://modern-sql.com/feature/filter
It's basically also a pivot technique: http://modern-sql.com/use-case/pivot
try the following code
declare #tab table (Comp varchar(50),Id varchar(50),Name varchar(50),Type varchar(50))
insert into #tab
Select 'AAA','D2222','Jon','BR11' Union ALL
Select 'AAA','D2222','Jon','BR12' Union ALL
Select 'AAA','D2865','Toe','BR11' Union ALL
Select 'BBB','D4151','Sue','BR11' Union ALL
Select 'BBB','D4151','Sue','BR12' Union ALL
Select 'BBB','D4151','Sue','BR13' Union ALL
Select 'CCC','D6080','Pete','BR14'Union ALL
Select 'CCC','D6723','Tom','BR13'
Select * from
(Select type,comp,count(*) cnt from #tab
group by type,Comp
)d
PIVOT
(Sum(Cnt) FOR Type in ([BR11],[BR12],[BR13],[BR14]))p
TRY THIS : Use CASE with SUM as below:
SELECT Comp,
SUM(CASE WHEN type = 'BR11' THEN 1 ELSE 0 END) br11,
SUM(CASE WHEN type = 'BR12' THEN 1 ELSE 0 END) br12,
SUM(CASE WHEN type = 'BR13' THEN 1 ELSE 0 END) br13,
SUM(CASE WHEN type = 'BR14' THEN 1 ELSE 0 END) br14
FROM CCDL
GROUP BY Comp
What you can do
SELECT Comp,
SUM(CASE WHEN type = 'BR11' THEN 1 ELSE 0 END) br11,
SUM(CASE WHEN type = 'BR12' THEN 1 ELSE 0 END) br12,
SUM(CASE WHEN type = 'BR13' THEN 1 ELSE 0 END) br13,
SUM(CASE WHEN type = 'BR14' THEN 1 ELSE 0 END) br14
FROM CCDL
GROUP BY Comp

SQL Server : transponation same like in excel

I have a table like this with over 100 rows (different times contains in column 7).
In my example I have 2 times BOB and 3 times EVA but eva or different name can be 10times(10rows with EVA) in there.
COLUMN1 COLUMN2 COLUMN3 COLUMN4 COLUMN5 COLUMN6 COLUMN7
DOG TAP KAP 28 7 672 BOB
MOUSE XY XY XY 16 672 BOB
DOG TAP KAP 6 5 525 EVA
MOUSE XY XY XY 2 525 EVA
CAT ZY XY XY 1 525 EVA
I expect result like this:
COLUMN1 COLUMN2 COLUMN3 COLUMN4 COLUMN5 COLUMN6 COLUMN7 COLUMN8 COLUMN9 COLUMN10 COLUMN11 COLUMN12 COLUMN13 COLUMN14 COLUMN15 COLUMN16 COLUMN 17
DOG TAP KAP 28 7 MOUSE XY XY XY 16 NULL NULL NULL NULL NULL 672 BOB
DOG TAP KAP 6 5 MOUSE XY XY XY 2 CAT ZY XY XY 1 525 EVA
I tried transponate in Excel like so:
=when(long(A2) > 0, A2, E1)
even I can do in Excel.
Thanks for opinions
The logic looks like this
;with cte as
(select t.*,
row_number() over (partition by column7 order by id) rn
from t
)
select
max(column1),max(column2),max(column3),max(column4),max(column5),
max(column8),max(column9),max(column10),max(column11),max(column12),
max(column15),max(column16),max(column17),max(column18),max(column19),
column100,column101
from
(
select
column6 as column100, column7 as column101,
case when cte.rn = 1 then cte.column1 end as column1,
case when cte.rn = 1 then cte.column2 end as column2,
case when cte.rn = 1 then cte.column3 end as column3,
case when cte.rn = 1 then cte.column4 end as column4,
case when cte.rn = 1 then cte.column5 end as column5,
case when cte.rn = 1 then cte.column6 end as column6,
case when cte.rn = 1 then cte.column7 end as column7,
case when cte.rn = 2 then cte.column1 end as column8,
case when cte.rn = 2 then cte.column2 end as column9,
case when cte.rn = 2 then cte.column3 end as column10,
case when cte.rn = 2 then cte.column4 end as column11,
case when cte.rn = 2 then cte.column5 end as column12,
case when cte.rn = 2 then cte.column6 end as column13,
case when cte.rn = 2 then cte.column7 end as column14,
case when cte.rn = 3 then cte.column1 end as column15,
case when cte.rn = 3 then cte.column2 end as column16,
case when cte.rn = 3 then cte.column3 end as column17,
case when cte.rn = 3 then cte.column4 end as column18,
case when cte.rn = 3 then cte.column5 end as column19,
case when cte.rn = 3 then cte.column6 end as column20,
case when cte.rn = 3 then cte.column7 end as column21
from cte
) s
group by s.column100,s.column101
But since you don't know the number of rows per name you need dynamic sql for example
declare #maxrn int
declare #i int
set #maxrn = (select max(rn) from
(select row_number() over (partition by column7 order by id) rn from t) s
)
--select #maxrn
set #i = 0
--select 'i=' , #i
declare #sqlstmt nvarchar(max)
set #sqlstmt = ';with cte as
(select t.*,
row_number() over (partition by column7 order by id) rn
from t
)
select '
while #i< #maxrn
begin
set #i = #i + 1
--select 'i=' , #i
set #sqlstmt =
concat(#sqlstmt,(
select concat(
'max(column' ,#i * 7 - 6, ') as column', #i * 7 - 6, ',',
'max(column' ,#i * 7 - 5, ') as column', #i * 7 - 5, ','
)
)
)
end
set #sqlstmt= concat(#sqlstmt, 'column', #maxrn * 7 + 10,' ,column' ,#maxrn * 7 + 11, ' from
(
select
column6 as column',#maxrn * 7 + 10,',',' column7 as column',#maxrn * 7 + 11,','
)
--select #sqlstmt
set #i = 0
while #i< #maxrn
begin
set #i = #i + 1
--select 'i=' , #i
set #sqlstmt =
concat(#sqlstmt,(
select concat(
'case when cte.rn = ' ,#i , ' then cte.column1 end as column', #i * 7 - 6,',',
'case when cte.rn = ',#i, ' then cte.column2 end as column', #i * 7 - 5 ,','
)
)
)
end
set #sqlstmt = concat(substring(#sqlstmt,1,len(#sqlstmt) - 1), ' from cte
) s
group by s.column' , #maxrn * 7 + 10, ', s.column', #maxrn * 7 + 11
)
--select #sqlstmt
exec sp_executesql #sqlstmt
Result
column1 column2 column8 column9 column15 column16 column31 column32
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
DOG TAP MOUSE XY NULL NULL 672 BOB
DOG TAP MOUSE XY CAT ZY 525 EVA
Warning: Null value is eliminated by an aggregate or other SET operation.
Note I have assumed there is an identity column in the data and I have not included all the columns (to keep the example down to a digestible size). The first bit works out the max rows per user, from this I can work out how many columns there will be in the output and what their names will be (assuming there are only 7 columns per row). Once the statement is built it is executed using sp_executesql.

Select rows horizontally in SQL Server 2005

I have Employee SQL Table (SQL Sever 2005):
EmployeeID Field1 Field2
121212 MISC1 ABC
121212 MISC2 XYZ
121213 MISC1 AAA
121213 MISC2 BBB
I would like to display the result like:
EmployeeID MISC1 MISC2
121212 ABC XYZ
121213 AAA BBB
Please advise and thank you in advance for your help.
You can do this using conditional aggregation
SELECT
EmployeeID,
MISC1 = MAX(CASE WHEN Field1 = 'MISC1' THEN Field2 END),
MISC2 = MAX(CASE WHEN Field1 = 'MISC2' THEN Field2 END)
FROM tbl
GROUP BY EmployeeID
If you want to do it dynamically:
DECLARE #sql NVARCHAR(MAX) = '';
SELECT #sql =
'SELECT
EmployeeID' + CHAR(10) +
(SELECT
' , MAX(CASE WHEN Field1 = ''' + Field1 +''' THEN Field2 END) AS ' + QUOTENAME(Field1) + CHAR(10)
FROM (
SELECT DISTINCT Field1 FROM tbl
)t
FOR XML PATH('')
) +
'FROM tbl
GROUP BY EmployeeID;';
EXEC(#sql);
Reference: Cross Tabs and Pivots by Jeff Moden

More efficient way to assign values to a column in SQL Server 2008 based on other column values

I have a table with 5 columns like:
id value1 value2 value3 Score
1 X X X
2 X Y Z
3 Y Z Z
4 X Z X
What I want is to assign final values equal to Ys and Zs (not X) for each column like:
id value1 value2 value3 final
1 X X X 0
2 X Y Z 2
3 Y Z Z 3
4 X Z X 1
The way I am doing it is:
Update table
set final = 3
where value1 <> 'X' and value2 <> 'X' and value3 <> 'X'
Update table
set final = 2
where (value1 <> 'X' and value2 <> 'X' and value3 = 'X')
OR (value1 = 'X' and value2 <> 'X' and value3 <> 'X')
OR (value1 <> 'X' and value2 = 'X' and value3 <> 'X')
Update table
set final = 1
where (value1 <> 'X' and value2 = 'X' and value3 = 'X')
OR (value1 = 'X' and value2 <> 'X' and value3 = 'X')
OR (value1 = 'X' and value2 = 'X' and value3 <> 'X')
Update table
set final = 0
where value1 = 'X' and value2 = 'X' and value3 = 'X'
I would like to ask if there is any smarter/more efficient way rather than this? Any advice would be appreciated. Thanks!
Is this what you want?
Update table
set final = ((case when value1 <> 'X' then 1 else 0 end) +
(case when value2 <> 'X' then 1 else 0 end) +
(case when value3 <> 'X' then 1 else 0 end)
);
This counts the number of values that are not X.
Here is another method:
Update table
set final = len(replace(value1 + value2 + value3, 'X', '');
Note: This only works if the columns really do have values that have only one character.
use CASE WHEN . . .
Update table
set final = CASE WHEN value1<>'X' and value2<>'X' and value3<>'X' THEN 3
WHEN (value1<>'X' and value2<>'X' and value3='X')
OR (value1='X' and value2<>'X' and value3<>'X')
OR (value1<>'X' and value2='X' and value3<>'X') THEN 2
WHEN (value1<>'X' and value2='X' and value3='X')
OR (value1='X' and value2<>'X' and value3='X')
OR (value1='X' and value2='X' and value3<>'X') THEN 1
WHEN value1='X' and value2='X' and value3='X' THEN 0
END
Using Computed column. Correct me if desired output is not obtained.
CREATE TABLE GRADES (
id INT
,VALUE1 VARCHAR(10)
,VALUE2 VARCHAR(10)
,VALUE3 VARCHAR(10)
,final INT AS (
(
CASE
WHEN value1 <> 'X'
THEN 1
ELSE 0
END
) + (
CASE
WHEN value2 <> 'X'
THEN 1
ELSE 0
END
) + (
CASE
WHEN value3 <> 'X'
THEN 1
ELSE 0
END
)
)
);
create TRIGGER test
ON [dbo].[YourTable]
AFTER INSERT
AS
BEGIN
declare #Id int
declare #value1 nvarchar(10)
declare #value2 nvarchar(10)
declare #value3 nvarchar(10)
declare #Count int =0
select top(1) #Id=id, #value1=[m1] ,#value2=[m2],#value3=[m3] from [dbo].[Table_3] order by id DESC
if #value1='x'
begin
set #Count=#Count+1
end
if #value2='x'
begin
set #Count=#Count+1
end
if #value3='x'
begin
set #Count=#Count+1
end
update [dbo].[Table_3]
set Score=#Count
where id =#Id
END