I am trying to combine multiple rows into one based on a unix timestamp which I created from a datetime using a self created scalar function.
I need to modify the T-SQL below so that lines that have the same timestamp are displayed on one row rather than multiple:
USE [NDTMS2Utils]
GO
SELECT [Timestamp],
[Logger],
[KeyIndicator],
[GeographicArea],
CASE
WHEN LocalAuthority = '- Restricted' THEN 'No LA Selected - Restricted'
WHEN LocalAuthority = '- Public' THEN 'No LA Selected - Public'
ELSE LocalAuthority
END AS LocalAuthority,
CASE
WHEN SubstanceGroup = '- Restricted' THEN 'All - Restricted'
WHEN SubstanceGroup = '- Public' THEN 'All - Public'
ELSE SubstanceGroup
END AS SubstanceGroup,
CASE
WHEN Gender = '- Restricted' THEN 'All - Restricted'
WHEN Gender = '- Public' THEN 'All - Public'
ELSE Gender
END AS Gender,
CASE
WHEN AgeGroup = '- Restricted' THEN 'All - Restricted'
WHEN AgeGroup = '- Public' THEN 'All - Public'
ELSE AgeGroup
END AS AgeGroup
FROM (
SELECT [dbo].[UNIX_TIMESTAMP]([Date]) AS [Timestamp],
[Logger],
CASE WHEN [Message] LIKE '%Key Indicator%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [KeyIndicator],
CASE WHEN [Message] LIKE '%Region%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [GeographicArea],
CASE WHEN [Message] LIKE '%Area%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [LocalAuthority],
CASE WHEN [Message] LIKE '%Substance Category%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [SubstanceGroup],
CASE WHEN [Message] LIKE '%Gender%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [Gender],
CASE WHEN [Message] LIKE '%AgeGroup%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [AgeGroup]
FROM [Log]
WHERE (Message LIKE '%ViewIt - View Data - the selected%') AND Logger != ''
GROUP BY [Date], [Logger], [Message]
UNION ALL
SELECT [dbo].[UNIX_TIMESTAMP]([Date]) AS [Timestamp],
'Public',
CASE WHEN [Message] LIKE '%Key Indicator' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Public') END AS [KeyIndicator],
CASE WHEN [Message] LIKE '%Region%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Public') END AS [GeographicArea],
CASE WHEN [Message] LIKE '%Area%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [LocalAuthority],
CASE WHEN [Message] LIKE '%Substance Category%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [SubstanceGroup],
CASE WHEN [Message] LIKE '%Gender%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [Gender],
CASE WHEN [Message] LIKE '%AgeGroup%' THEN LTRIM(REPLACE(SUBSTRING([Message], CHARINDEX(':', [Message]), LEN([Message])), ':', '') + ' - Restricted') END AS [AgeGroup]
FROM [Log]
WHERE (Message LIKE '%ViewIt - View Data - the selected%') AND Logger = ''
GROUP BY [Date], [Logger], [Message]
) AS f
ORDER BY CONVERT([Date], GETDATE()) ASC, [Logger]
Currently the data looks like this when the above query is run:
The table below shows the format that I am trying achieve:
How do I modify the query to display the results above?
This is a simple CROSS TAB problem, note this article by Jeff Moden.
Since you don't have any DDL or easily consumable sample data I created my own simplified sample data that should be enough.
-- Sample Table
DECLARE #yourtable TABLE
(
TStamp BIGINT,
Logger VARCHAR(40),
Pet VARCHAR(20),
Car VARCHAR(30),
Fruit VARCHAR(20)
);
-- Sample Data
INSERT #yourtable (TStamp,Logger,Pet,Car,Fruit)
VALUES
(154377379, '07F09981-C723-4DB3-A4C4-2842F26D102A',NULL,NULL,'Apple'),
(154377379, '07F09981-C723-4DB3-A4C4-2842F26D102A',NULL,'Porche',NULL),
(154377379, '07F09981-C723-4DB3-A4C4-2842F26D102A','Cat',NULL,NULL),
(151173333, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422',NULL,NULL,'Orange'),
(151173333, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422',NULL,'Subaru',NULL),
(151173333, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422','Frog',NULL,NULL),
(151177855, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422',NULL,NULL,'Grapes'),
(151177855, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422',NULL,'Hovercraft',NULL),
(151177855, '84BEDA9D-D525-4A95-B1D7-4D9A74EB0422','Bird',NULL,NULL);
-- Solution
SELECT
TStamp = t.TStamp,
Logger = T.Logger,
Pet = MAX(CASE WHEN t.Pet IS NOT NULL THEN t.Pet END),
Car = MAX(CASE WHEN t.Car IS NOT NULL THEN t.Car END),
Fruit = MAX(CASE WHEN t.Fruit IS NOT NULL THEN t.Fruit END)
FROM #yourtable AS t
GROUP BY t.TStamp, t.Logger;
Results:
TStamp Logger Pet Car Fruit
----------- ---------------------------------------- ------ ------------ --------
154377379 07F09981-C723-4DB3-A4C4-2842F26D102A Cat Porche Apple
151173333 84BEDA9D-D525-4A95-B1D7-4D9A74EB0422 Frog Subaru Orange
151177855 84BEDA9D-D525-4A95-B1D7-4D9A74EB0422 Bird Hovercraft Grapes
Related
I'm trying to populate the field of an XML file with either '0', if a specific column (pv_an4) does not exist, OR with the value of the column, if it exists.
This is my code so far:
XMLELEMENT( Name "Telephone",
case
when not exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then ''
when exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then pv_an4
end ),
When I execute this I get this error:
FEHLER: Column »pv_an4« does not exist ZEILE 25: ...E_NAME =
'phonebook' AND COLUMN_NAME = 'pv_an4') then pv_an4
But this does make no sense to me, because for example with this code it would work:
....
when exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then 'pv_an4 exists'
end ),
....
I've spent the whole day trying to solve this problem, could someone hint me in the right direction, please?
/edit: Full query right below:
SELECT
XMLFOREST( xmlpb.entry as "DivinusIPPhoneDirectory" )
FROM (
SELECT
XMLCONCAT (
XMLELEMENT ( NAME "Title", 'Phonelist' ),
XMLELEMENT ( NAME "Prompt", 'Prompt' ),
XMLAGG (
XMLELEMENT (
NAME "DirectoryEntry",
XMLELEMENT( Name "Name",
case
when (pb.company = '') IS FALSE AND pb.lastname != '' and pb.firstname != '' then pb.company || ' - ' || pb.lastname || ', ' || pb.firstname
when (pb.company = '') IS FALSE AND pb.lastname != '' and pb.firstname = '' then pb.company || ' - ' || pb.lastname
when (pb.company = '') IS FALSE AND pb.lastname = '' and pb.firstname = '' then pb.company
when (pb.company = '') IS FALSE AND pb.lastname = '' and pb.firstname != '' then pb.company || ' - ' || pb.firstname
when (pb.company = '') IS NOT FALSE AND pb.lastname != '' and pb.firstname != '' then pb.lastname || ', ' || pb.firstname
when (pb.company = '') IS NOT FALSE AND pb.lastname != '' and pb.firstname = '' then pb.lastname
end ),
XMLELEMENT( Name "Telephone", pb.pv_an3 ),
XMLELEMENT( Name "Telephone",
case
when not exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then ''
else pb.pv_an4
end ),
XMLELEMENT( Name "Telephone", pb.phonenumber ),
XMLELEMENT( Name "Telephone", pb.pv_an1 ),
XMLELEMENT( Name "Telephone", pb.pv_an2 )
)
)
) as entry
FROM
phonebook pb
WHERE fkidtenant = 1
The whole sql statement is parsed and compiled before it is run, therefore postgresql will complain of the missing field. There is no shortcut.
You need to use dynamically generated sql if you want to handle such scenarios (check whether the column exists and create the appropriate sql statement). Although I cannot really imagine why you should not know if a certain column exists in a table or not.
Try:
XMLELEMENT( Name "Telephone",
case
when not exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then ''
when exists (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'phonebook' AND COLUMN_NAME = 'pv_an4') then 'pv_an4'
end ),
In line 4, you're using pv_an4 as a column in your first query, but as a column value in your second query.
I need to parse a full name in the format, prefix first middle last suffix, but not all parts may be included. I have the prefix first middle and last working, but Jr gets stuffed in with the last name. How do I get the suffix to come out in a suffix column? Example includes data.
SELECT
FIRST_NAME.INPUT_DATA
,FIRST_NAME.PREFIX
,FIRST_NAME.FIRST_NAME
,CASE WHEN 0 = CHARINDEX(' ',FIRST_NAME.REMAINING)
THEN NULL --no more spaces found, consider remaining to be last name
ELSE SUBSTRING(
FIRST_NAME.REMAINING
,1
,CHARINDEX(' ',FIRST_NAME.REMAINING)-1
)
END AS MIDDLE_NAME
,SUBSTRING(
FIRST_NAME.REMAINING
,1 + CHARINDEX(' ',FIRST_NAME.REMAINING)
,LEN(FIRST_NAME.REMAINING)
) AS LAST_NAME
FROM
(
SELECT
PREFIX.PREFIX
,CASE WHEN 0 = CHARINDEX(' ',PREFIX.REMAINING)
THEN PREFIX.REMAINING --no space found, return the entire string
ELSE SUBSTRING(
PREFIX.REMAINING
,1
,CHARINDEX(' ',PREFIX.REMAINING)-1
)
END AS FIRST_NAME
,CASE WHEN 0 = CHARINDEX(' ',PREFIX.REMAINING)
THEN NULL --no spaces found, consider to be first name
ELSE SUBSTRING(
PREFIX.REMAINING
,CHARINDEX(' ',PREFIX.REMAINING)+1
,LEN(PREFIX.REMAINING)
)
END AS REMAINING
,PREFIX.INPUT_DATA
FROM
(
SELECT --CLEAN_DATA
--if first three characters match list,
--parse as a "PREFIX". else return NULL for PREFIX.
CASE WHEN SUBSTRING(CLEAN_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(CLEAN_DATA.FULL_NAME,1,3)))
ELSE NULL
END AS PREFIX
,CASE WHEN SUBSTRING(CLEAN_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(CLEAN_DATA.FULL_NAME,4,LEN(CLEAN_DATA.FULL_NAME))))
ELSE LTRIM(RTRIM(CLEAN_DATA.FULL_NAME))
END AS REMAINING
,CLEAN_DATA.INPUT_DATA
FROM
(
SELECT
--trim leading & trailing spaces to prepare for processing
--replace extra spaces in name
REPLACE(REPLACE(LTRIM(RTRIM(FULL_NAME)),' ',' '),' ',' ') AS FULL_NAME
,FULL_NAME AS INPUT_DATA
FROM
(
--test with test data, or table
--table
--SELECT CONTACT AS FULL_NAME
--FROM CONTACT
--test data
--/*
SELECT 'Andy D Where' AS FULL_NAME
UNION SELECT 'Cathy T Landers' AS FULL_NAME
UNION SELECT 'Ms Annie Wint There' AS FULL_NAME
UNION SELECT 'Frank Fields' AS FULL_NAME
UNION SELECT 'Howdy U Pokes Jr.' AS FULL_NAME
--*/
) SOURCE_DATA
) CLEAN_DATA
) PREFIX
) FIRST_NAME
--credits to JStyons of course
Hope this helps. I have only added Generational SUFFIX titles(Sr, Jr), If more are needed you could add to the Case statement as needed. I am also assuming that your Db is case insensitive.
Assumption (Business Rules):
First Name has no spaces
Middle Name has no spaces
Last name has no spaces
Prefix's are only of the form 'MR ','MS ','DR ','MRS' with no period "."
Suffix's are only of the form 'Sr', 'Jr', 'Sr.', 'Jr.'
The Database is case insensitive
IF OBJECT_ID('tempdb..#cte_SpaceFix') IS NOT NULL
DROP TABLE #cte_SpaceFix
;WITH cte_OriginalData (FullName)
AS (
SELECT 'Andy D Where'
UNION
SELECT 'Cathy T Landers'
UNION
SELECT 'Ms Annie Wint There'
UNION
SELECT 'Ms Annie Wint There Jr'
UNION
SELECT 'Mrs Annie There Jr'
UNION
SELECT 'Frank Fields'
UNION
SELECT 'Howdy U Pokes Jr.'
UNION
SELECT 'Howdy U Pokes Sr.'
UNION
SELECT 'Cathy T Landers Jr'
UNION
SELECT 'Landers Jr'
)
,cte_FullNameRemoveTail AS
(
SELECT LTRIM(RTRIM(FullName)) AS FullName
FROM cte_OriginalData
)
,cte_Parse_Prefix(Prefix,FullFirst_Prefix,FullName) AS
(
SELECT CASE
WHEN SUBSTRING(FullName, 1, 3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(FullName, 1, 3)))
ELSE NULL
END AS Prefix,
CASE
WHEN SUBSTRING(FullName, 1, 3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(FullName, 4, 8000)))
ELSE LTRIM(RTRIM(FullName))
END AS FullFirst_Prefix,
FullName
FROM cte_FullNameRemoveTail
)
,cte_Parse_Suffix(Prefix,FullFirst_Prefix_Suffix,Suffix,FullName) AS
(
SELECT Prefix,
CASE
WHEN RIGHT(FullFirst_Prefix,3) = ' JR' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-3)))
WHEN RIGHT(FullFirst_Prefix,4) = ' JR.' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-4)))
WHEN RIGHT(FullFirst_Prefix,3) = ' SR' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-3)))
WHEN RIGHT(FullFirst_Prefix,4) = ' SR.' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-4)))
ELSE LTRIM(RTRIM(FullFirst_Prefix))
END AS FullFirst_Prefix_Suffix,
CASE
WHEN RIGHT(FullFirst_Prefix,3) = ' JR'
OR RIGHT(FullFirst_Prefix,4) = ' JR.'
THEN 'Jr'
WHEN RIGHT(FullFirst_Prefix,3) = ' SR'
OR RIGHT(FullFirst_Prefix,4) = ' SR.'
THEN 'Sr'
ELSE NULL
END AS Suffix,
FullName
FROM cte_Parse_Prefix
)
,cte_SpaceFix(Prefix, FullFirst_Prefix_Suffix, Suffix, FullName) AS
(
SELECT Prefix,
CASE
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) > 2 THEN REPLACE(REPLACE(REPLACE(REPLACE(FullFirst_Prefix_Suffix,SPACE(5), SPACE(1)),SPACE(4), SPACE(1)),SPACE(3), SPACE(1)),SPACE(2), SPACE(1))
ELSE FullFirst_Prefix_Suffix
END AS FullFirst_Prefix_Suffix,
Suffix,
FullName
FROM cte_Parse_Suffix
)
SELECT * INTO #cte_SpaceFix
FROM cte_SpaceFix
;WITH cte_Parse_FirstName(Prefix, FirstName, Suffix, FullFirst_Prefix_Suffix_FirstName, FullName) AS
(
SELECT Prefix,
CASE
WHEN FullFirst_Prefix_Suffix IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) >= 1 THEN LEFT(FullFirst_Prefix_Suffix,CHARINDEX(' ',FullFirst_Prefix_Suffix))
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) = 0 THEN FullFirst_Prefix_Suffix
ELSE NULL
END AS FirstName,
Suffix,
CASE
WHEN FullFirst_Prefix_Suffix IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) >= 1 THEN LTRIM(RTRIM(REPLACE(FullFirst_Prefix_Suffix,LEFT(FullFirst_Prefix_Suffix,CHARINDEX(' ',FullFirst_Prefix_Suffix)),'')))
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) = 0 THEN NULL
ELSE NULL
END AS FullFirst_Prefix_Suffix_FirstName,
FullName
FROM #cte_SpaceFix
)
,cte_Parse_LastName(Prefix, FirstName, LastName, Suffix, MiddleName, FullName) AS
(
SELECT Prefix,
FirstName,
CASE
WHEN FullFirst_Prefix_Suffix_FirstName IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) >= 1 THEN SUBSTRING(FullFirst_Prefix_Suffix_FirstName,CHARINDEX(' ',FullFirst_Prefix_Suffix_FirstName)+1,8000)
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) = 0 THEN FullFirst_Prefix_Suffix_FirstName
ELSE NULL
END AS LastName,
Suffix,
CASE
WHEN FullFirst_Prefix_Suffix_FirstName IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) >= 1 THEN LEFT(FullFirst_Prefix_Suffix_FirstName,CHARINDEX(' ',FullFirst_Prefix_Suffix_FirstName))
ELSE NULL
END AS MiddleName,
FullName
FROM cte_Parse_FirstName
)
SELECT Prefix, FirstName, MiddleName, LastName, Suffix--, FullName
FROM cte_Parse_LastName
IF OBJECT_ID('tempdb..#cte_SpaceFix') IS NOT NULL
DROP TABLE #cte_SpaceFix
SELECT user
FROM userlist zH with(nolock)
where zH.user in (case when zh.trait='1' then ('B', 'HO', 'KO', 'PL','APP','2A','2B') else ('O') end)
can this statement with the where-in-case work? i hope you get what i meant. thanks.
You can use nested case statement, like
SELECT user
FROM userlist zH with(nolock)
where 'true' =
(case when zh.trait = '1'
then
case when zH.user in ('B', 'HO', 'KO', 'PL','APP','2A','2B')
then 'true'
else 'false'
end
else
case when zH.user = 'O'
then 'true'
else 'false'
end
end)
SELECT [user]
FROM userlist zH WITH ( NOLOCK )
WHERE ( zh.trait = '1'
AND zH.[user] IN ( 'B', 'HO', 'KO', 'PL', 'APP', '2A', '2B' )
)
OR ( zh.trait <> '1'
AND zH.[user] IN ( 'O' )
)
I have created stored procedure which creates pivoted table as below. The problem is that it doesn't work as expected because it doesn't change nulls to zeros. Could You please show me the right direction?
create procedure sp_system_counts
as
declare #columns nvarchar(max)
declare #columnscondition nvarchar(max)
declare #query nvarchar(max)
select distinct systemgroup, systemgroupsortorder into #temp_table_system_group
from systemgroups
where systemgroup not like 'N/A'
order by systemgroupsortorder
select #columns = isnull(#columns + ',', '') + '[' + convert(varchar, systemgroup) + ']' FROM #temp_table_system_group
select #columnscondition = + isnull(#columnscondition + ' or ', '') + '[' + convert(varchar, systemgroup) + '] <> 0' FROM #temp_table_system_group
--select #columns
create table #temp_systems (
systemid int,
systemnane varchar(max),
region varchar(50),
systemgroup varchar(50),
remsid int,
remscode int)
insert into #temp_systems
select distinct sy.systemid, sy.systemname, co.region, syg.systemgroup, re.remsid, re.remscode
from systems sy
inner join servers se on sy.systemid = se.systemid and sy.systemid = sy.systemid
inner join rems re on se.remsid = re.remsid
inner join cities ci on re.cityid = ci.cityid
inner join countries co on ci.countryid = co.countryid
inner join systemmodels sym on sy.systemmodelid = sym.systemmodelid
inner join systemtypes syt on sym.systemtypeid = syt.systemtypeid
inner join systemgroups syg on syt.systemgroupid = syg.systemgroupid
where syg.systemgroup not like 'N/A'
order by syg.systemgroup
set #query = '
select region, ' + #columns + '
from (
select distinct region, systemgroup, cnt = isnull(count(systemid),0) from #temp_systems
group by region, systemgroup
with rollup) p
pivot (sum (cnt) for systemgroup in (' + #columns + ')) as asd
where (' + #columnscondition +')'
execute(#query)
drop table #temp_table_system_group
drop table #temp_systems
I'm not sure, about logic implemented here, but may be it will help, if you change:
select #columns = isnull(#columns + ',', '') + '[' + convert(varchar, systemgroup) + ']' FROM #temp_table_system_group
select #columnscondition = + isnull(#columnscondition + ' or ', '') + '[' + convert(varchar, systemgroup) + '] <> 0' FROM #temp_table_system_group
to
select #columns = isnull(#columns + ',', '') + 'isnull(' + quotename(convert(varchar, systemgroup)) + ', 0) as ' + quotename(convert(varchar, systemgroup)) FROM #temp_table_system_group
select #columnscondition = + isnull(#columnscondition + ' or ', '') + 'isnull(' + quotename(convert(varchar, systemgroup)) + ', 0) <> 0' FROM #temp_table_system_group
i.e. doing isnull(.., 0) over pivoted data, not before pivoting
I have the following table where all fields except Value as a part of a unique index on the table. I'd like to inherit the Value from a record with Value<>NULL to the next revision record only if that record has a NULL value (See example below):
Var[n]Value fields ate varchar and there maybe 1-n number of Var[n]value fields in my table.
Source:
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 NULL NULL
1744 6 2 1 NULL SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 NULL
Needed result (notice change for revision records 5 and 6 var1value and 5,8 for var2value):
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 Tit2 ABD
1744 6 2 1 Tit2 SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 AS
Any idea how to handle it by SQL?
Please advise.
I tried the following:
declare #TableName as VarChar(32) = 'MYTABLE'
declare #SetClause as VarChar(1024)
declare #LWhereClause as VarChar(1024)
declare #RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = #TableName and Column_Name like 'Var%'
--select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare #ColumnName as VarChar(32)
while ( ##RowCount > 0 )
begin
select top 1 #ColumnName = Column_Name
from #Columns
order by Column_Name
set #SetClause = case when #SetClause is NULL then '' else #SetClause + ', ' end +
#ColumnName + ' = Coalesce( L.' + #ColumnName + ', R.' + #ColumnName + ' )'
set #LWhereClause = case when #LWhereClause is NULL then '' else #LWhereClause + ' or ' end +
'L.' + #ColumnName + ' is NULL'
set #RWhereClause = case when #RWhereClause is NULL then '' else #RWhereClause + ' or ' end +
'R.' + #ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = #ColumnName
end
--select #SetClause, #LWhereClause, #RWhereClause
-- Put together the UPDATE statement.
declare #Update as nVarChar(max)
set #Update=''
set #Update=#Update +
'update L set ' + #SetClause + ' from ' + #TableName +
' as L inner join ' + #TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + #LWhereClause + ' ) and ( ' + #RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare #Loop as nVarChar(max)
set #Loop =''
set #Loop=#Loop+
'#declare Eleanor as Int = 42;
while ( #Eleanor > 0 ) '
+ #Update + '
set #Eleanor = ##RowCount
end'
--select #Loop
-- Execute it.
exec #Loop
drop table #Columns
and I get the following error on exec loop. Why it is truncating the nvarchar string?
Msg 203, Level 16, State 2, Line 53
The name '#declare Eleanor as Int = 42;
while ( #Eleanor > 0 ) update L set variable104 = Coalesce( L.variable104, R.variable104 ), variable105 = Coalesce( L.variable105, R.variable105 ), variable106 = Coalesce( L.variable106, R.variable106 ), variable107 = Coalesce( L.variable107, R.variable107 ), variable112 = Coalesce( L.variable112, R.variable112 ), variable116 = Coalesce( L.variable116, R.variable116 ), variable119 = Coalesce( L.variable119, R.variable119 ), variable120 = Coalesce( L.variable120, R.variable120 ), variable121 = Coalesce( L.variable121, R.variable121 ), variable122 = Coalesce( L.variable122, R.variable122 ), variable124 = Co' is not a valid identifier.
exact duplicate of :
SQL QUERY replace NULL value in a row with a value from the previous known value
p.s:i don't have privilege to comment.so i wrote as answer.
EDIT: Begging your pardon, but I failed to consider the variable columns.
This query will retrieve the columns defined in YourTable:
select Column_Name from Information_Schema.Columns where Table_Name = 'YourTable'
Thereafter, you need to build a dynamic query and EXEC it. You could craft code like that shown below for each individual column, or to process all of the columns in one go.
Building the query dynamically is a somewhat tedious process. The following should get you well on your way.
declare #TableName as VarChar(32) = 'YourTable'
declare #SetClause as VarChar(1024)
declare #LWhereClause as VarChar(1024)
declare #RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = #TableName and Column_Name like 'Var%'
select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare #ColumnName as VarChar(32)
while ( ##RowCount > 0 )
begin
select top 1 #ColumnName = Column_Name
from #Columns
order by Column_Name
set #SetClause = case when #SetClause is NULL then '' else #SetClause + ', ' end +
#ColumnName + ' = Coalesce( L.' + #ColumnName + ', R.' + #ColumnName + ' )'
set #LWhereClause = case when #LWhereClause is NULL then '' else #LWhereClause + ' or ' end +
'L.' + #ColumnName + ' is NULL'
set #RWhereClause = case when #RWhereClause is NULL then '' else #RWhereClause + ' or ' end +
'R.' + #ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = #ColumnName
end
select #SetClause, #LWhereClause, #RWhereClause
-- Put together the UPDATE statement.
declare #Update as VarChar(4096) =
'update L set ' + #SetClause + ' from ' + #TableName +
' as L inner join ' + #TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + #LWhereClause + ' ) and ( ' + #RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare #Loop as VarChar(4096) =
'#declare Eleanor as Int = 42; ...' + #Update + '...'
select #Loop
-- Execute it.
exec #Loop
drop table #Columns
Here's one dreadful way that is based on revision numbers being dense:
declare #Docs as Table ( DocId Int, Rev Int, Proj Int, Conf Int, Var1 VarChar(10) Null, Var2 VarChar(10) Null )
insert into #Docs ( DocId, Rev, Proj, Conf, Var1, Var2 ) values
( 1744, 1, 2, 1, NULL, NULL ),
( 1744, 2, 2, 1, NULL, NULL ),
( 1744, 3, 2, 1, 'Tit1', 'ABC' ),
( 1744, 4, 2, 1, 'Tit2', 'ABD' ),
( 1744, 5, 2, 1, NULL, NULL ),
( 1744, 6, 2, 1, NULL, 'SDC' ),
( 1744, 7, 2, 1, '', 'AS' ), -- The example data for this row is unclear.
( 1744, 8, 2, 1, 'Tit3', NULL )
select * from #Docs
declare #Eleanor as Int = 42
while ( #Eleanor > 0 )
begin
update L
set Var1 = Coalesce( L.Var1, R.Var1 ), Var2 = Coalesce( L.Var2, R.Var2 )
from #Docs as L inner join
#Docs as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf
where ( L.Var1 is NULL or L.Var2 is NULL ) and ( R.Var1 is not NULL or R.Var2 is not NULL )
set #Eleanor = ##RowCount
end
select * from #Docs