TSQL IF Operator results invalid column - sql-server

My objective, is to select the first available address. If there isn't a AddressCity, then I should select the AddressRegion, and if there is not a AddressRegion I should select the AddressCountry.
IF AddressCity IS NOT NULL
SELECT AddressName + ' is from ' + AddressCity
ELSE
IF AddressRegion IS NOT NULL
SELECT Address+ ' is from ' + AddressRegion
ElSE
IF AddressCountry IS NOT NULL
SELECT AddressName + ' is from ' + AddressCountry
FROM DBO.Address
When I execute it, I get Invalid column name 'AddressCity'

You want something like case or coalesce():
SELECT coalesce(AddressName + ' is from ' + AddressCity,
AddressName + ' is from ' + AddressRegion
AddressName + ' is from ' + AddressCountry
)
FROM DBO.Address;

Related

Trying to learn SQL

I have a select statement that strings the name together. The issue is that I want to put a period after the middle initial but when it is blank the period is after the firstname. Here is the select
select LTrim(RTrim(FirstName + ' ' + Left(MiddleName,1))) + '. ' + LastName as FullName,
Just add a case
select LTrim(RTrim(FirstName + ' ' + case when isnull(MiddleName,'')='' then else Left(MiddleName,1))) + '. ' end + LastName as FullName,
You could test for the existance of the MiddleName and only include your period if its not null
SELECT
LTRIM(RTRIM(FirstName + ' ' + IIF(ISNULL(MiddleName,'')<>'',LEFT(MiddleName,1) + '.', ''))) + ' ' + LastName as FullName
Use Case statement to check if the string is not empty
select LTrim(RTrim(FirstName + ' ' + Left(MiddleName,1))) +
case when Left(MiddleName,1) <> '' then '. ' else '' end + LastName as FullName,

SQL Stored Procedure How to Modify and Return the Result of an Executed Dynamic Query

I have created a stored procedure that returns a single string of concatenated fields. The issue is that some of these fields may be empty strings resulting in a string much like the below:
, Mendip Road, Farnborough, Hampshire, GU14 9LS
or even
, , Farnborough, Hampshire, GU14 9LS
I really want to strip off any leading commas but I'll only know this once the query has been executed. Is there a way of executing the query, pattern-matching the commas and then removing them before finally returning the modified string?
The query itself is as follows:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI,'''') + '', '' + ISNULL(Name,'''') + '', '''
+ ' + ISNULL(Settlement,'''') + '', '' + ISNULL(Cou_Unit,'''') + '', '' + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
EXECUTE(#SQLQuery)
Concatenate the comma inside the ISNULL expression as follows:
ISNULL(POI + ', ','')
so your query will look like:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI + '', '','''') + ISNULL(Name + '', '','''')'
+ ' + ISNULL(Settlement + '', '','''') + ISNULL(Cou_Unit + '', '','''') + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
I don't know if you need dynamic SQL for some other reason, but I think something like this should work (with no Dynamic SQL); if you're really sure you need Dynamic SQL for some other reason, then just refactor this idea into your Dynanmic Statement:
DECLARE #ClosestAddress VARCHAR(1000)
SELECT TOP 1
#ClosestAddress = ISNULL(POI + ', ','')
+ ISNULL(Name + ', ','')
+ ISNULL(Settlement + ', ','')
+ ISNULL(Cou_Unit + ', ', '')
+ ISNULL(Postcode,'')
--AS ClosestAddress
FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY (Longitude = 12.2132) * (Longitude = 12.2132) + (Latitude - 12.2132) * (Latitude - 12.2132) ASC
IF (RIGHT(#ClosestAddress, 2) = ', ')
RETURN SUBSTRING(#ClosestAddress, 0, LEN(#ClosestAddress))
ELSE
RETURN #ClosestAddress
Why this should work: Concatenating NULL + ', ' will result in an empty string. Then we check if the string ends with ', ', and if so we return everything but the last two characters.
You could do something like Replace all Comma with space and then do LTRIM and RTRIM and replace all space with comma.
Create table Data(name varchar(10),lastname varchar(10));
insert into Data values('','Doe');
insert into Data values('Jane','Doe');
insert into Data values('Jane','');
SELECT Replace(Rtrim(Ltrim(Replace(ISNULL(name,'') +',' + ISNULL(lastname,'') + ',',',',' '))),' ',',')
from Data
something like : http://sqlfiddle.com/#!3/6a6c6/1

Compile error - Dynamic SQL

I've tried to implement some dynamic SQL to create a cursor as an extension of a simple SELECT query. The cursor is used as a way to print the GROUPED values returned from the SELECT as a message in SQL Server Management Studio (kind of like a visual summary of the data) . The purpose of this approach is half task related and half to benefit my understanding of how dynamic SQL can be developed. Code reads:
DECLARE #Focus VARCHAR(10);
SET #Focus = 'Completed'; /* User input event focus {Started, Completed} */
DECLARE #PeriodStartDate DATE, #PeriodEndDate DATE;
SET #PeriodStartDate = '04/01/2014';
SET #PeriodEndDate = GETDATE();
DECLARE #sql VARCHAR(MAX);
SET #sql =
'SELECT ' +
'CASE DATEPART(M, ' + '[Event ' + CASE #Focus
WHEN 'Started' THEN 'Start'
WHEN 'Completed' THEN 'End'
END + ' Date]) ' +
' WHEN 1 THEN ''January'' ' +
' WHEN 2 THEN ''February'' ' +
' WHEN 3 THEN ''March'' ' +
' WHEN 4 THEN ''April'' ' +
' WHEN 5 THEN ''May'' ' +
' WHEN 6 THEN ''June'' ' +
' WHEN 7 THEN ''July'' ' +
' WHEN 8 THEN ''August'' ' +
' WHEN 9 THEN ''September'' ' +
' WHEN 10 THEN ''October'' ' +
' WHEN 11 THEN ''November'' ' +
' WHEN 12 THEN ''December'' ' +
' END AS [Event ' + #Focus + ' Month], ' +
' COUNT([Unique ID]) AS [Number of Events] ' +
' FROM [udf_Events](' + #Focus + ', ' + CAST(#PeriodStartDate AS VARCHAR) + ', ' + CAST(#PeriodEndDate AS VARCHAR) + ') ' +
' GROUP BY ' +
' DATEPART(M, ' + '[Event ' + CASE #Focus
WHEN 'Started' THEN 'Start'
WHEN 'Completed' THEN 'End'
END + ' Date]) ' +
' ORDER BY ' +
' DATEPART(M, ' + '[Event ' + CASE #Focus
WHEN 'Started' THEN 'Start'
WHEN 'Completed' THEN 'End'
END + ' Date]) '
;
DECLARE Results CURSOR
FOR
SELECT
#sql;
The error message I receive:
Msg 16924, Level 16, State 1, Line 71 Cursorfetch: The number of
variables declared in the INTO list must match that of selected
columns.
Through grappling with the problem and trying to execute the query as a SELECT statement (removing the complexity of the cursor) using EXEC(#sql) the error message reads:
Invalid column name 'Completed'.
..Which leads me to believe the problem lies with the CASE expression in the first field selected. udf_Events is an in-line table valued function with three arguments. Amongst others, it has columns [Event Start Date] and [Event End Date] which are the values the cursor is looking to do its work on.
Try this...few ' were missing in your query
DECLARE #Focus VARCHAR(10);
SET #Focus = 'Completed'; /* User input event focus {Started, Completed} */
DECLARE #temp VARCHAR(500);
IF(#Focus = 'Completed')
SET #temp = '[Event End Date]'
ELSE
SET #temp = '[Event Start Date]'
DECLARE #PeriodStartDate DATE, #PeriodEndDate DATE;
SET #PeriodStartDate = '04/01/2014';
SET #PeriodEndDate = GETDATE();
DECLARE #sql VARCHAR(MAX);
SET #sql =
'SELECT ' +
'CASE DATEPART(M, ' + #temp + ')' +
' WHEN 1 THEN ''January'' ' +
' WHEN 2 THEN ''February'' ' +
' WHEN 3 THEN ''March'' ' +
' WHEN 4 THEN ''April'' ' +
' WHEN 5 THEN ''May'' ' +
' WHEN 6 THEN ''June'' ' +
' WHEN 7 THEN ''July'' ' +
' WHEN 8 THEN ''August'' ' +
' WHEN 9 THEN ''September'' ' +
' WHEN 10 THEN ''October'' ' +
' WHEN 11 THEN ''November'' ' +
' WHEN 12 THEN ''December'' ' +
' END AS [Event ' + #Focus + ' Month], ' +
' COUNT([Unique ID]) AS [Number of Events] ' +
' FROM [udf_Events](''' + #Focus + ''', ''' + CAST(#PeriodStartDate AS VARCHAR) + ''', ''' + CAST(#PeriodEndDate AS VARCHAR) + ''') ' +
' GROUP BY ' +
' DATEPART(M, ' + #temp + ')' +
' ORDER BY ' +
' DATEPART(M, ' + #temp + ')';
print #sql
You're not quoting the dates in the call to udf_Events so you end up with
[udf_Events](Completed, 2014-04-01, 2014-09-19)
instead of
[udf_Events](Completed, '2014-04-01', '2014-09-19')
The fix is to change the line
' FROM [udf_Events](' + #Focus + ', ' + CAST(#PeriodStartDate AS VARCHAR) + ', ' + CAST(#PeriodEndDate AS VARCHAR) + ') ' +
to
' FROM [udf_Events](' + #Focus + ', ''' + CAST(#PeriodStartDate AS VARCHAR) + ''', ''' + CAST(#PeriodEndDate AS VARCHAR) + ''') ' +
That said, if the parameters to udf_Events are datetimes then I would consider changing the format to YYYYMMDD as this is unambiguous. To do this you can use CONVERT(char(8), <date>, 112) where <date> is the date to be converted.
i.e:
' FROM [udf_Events](' + #Focus + ', ''' + CONVERT(char(8), #PeriodStartDate, 112) + ''', ''' + CONVERT(char(8), #PeriodEndDate, 112) + ''') ' +

Stored Procedure with a conditional?

I trying to rewrite a stored procedure and my SQL is not very good. What i'm hoping to do is write it so that if ModuleID is 555 then select a custom date range (eg. 2012-01-01 2012-12-31). The Current SP is below.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
/*** EventsGetByRange ***/
ALTER PROCEDURE [dbo].[EventsGetByRange]
(
#Filter nvarchar(500),
#BeginDate datetime,
#EndDate datetime
)
AS
SET DATEFORMAT mdy
Declare #sql nvarchar(4000)
Select #sql = 'SELECT E.PortalID, E.EventID, E.RecurMasterID, E.ModuleID, E.EventDateBegin, E.EventDateEnd, '
+ 'E.EventTimeBegin, E.Duration, E.EventName, E.EventDesc, '
+ 'E.Importance, E.CreatedDate, '
+ 'CreatedBy = U.DisplayName, '
+ 'CreatorID = E.CreatedBy, '
+ 'E.Every, '
+ 'E.Period, '
+ 'E.RepeatType, '
+ 'E.Notify, '
+ 'E.approved, '
+ 'E.Signups, '
+ 'E.MaxEnrollment, '
+ '(Select count(*) from dbo.EventsSignups WHERE EventID = E.EventID and E.Signups = 1) as Enrolled, '
+ 'E.EnrollRoleID, '
+ 'E.EnrollFee, '
+ 'E.EnrollType, '
+ 'E.PayPalAccount, '
+ 'E.PayPalPassword, '
+ 'E.Cancelled, '
+ 'E.DetailPage, '
+ 'E.DetailNewWin, '
+ 'E.DetailURL, '
+ 'E.ImageURL, '
+ 'E.ImageType, '
+ 'E.ImageWidth, '
+ 'E.ImageHeight, '
+ 'E.ImageDisplay, '
+ 'E.Location, '
+ 'c.LocationName, '
+ 'c.MapURL, '
+ 'E.Category, '
+ 'b.CategoryName, '
+ 'b.Color, '
+ 'b.FontColor, '
+ 'E.Reminder, '
+ 'E.TimezoneOffset, '
+ 'E.SendReminder, '
+ 'E.ReminderTime, '
+ 'E.ReminderTimeMeasurement, '
+ 'E.ReminderFrom, '
+ 'E.SearchSubmitted, '
+ 'E.CustomField1, '
+ 'E.CustomField2, '
+ 'E.EnrollListView, '
+ 'E.DisplayEndDate, '
+ 'E.AllDayEvent, '
+ 'E.OwnerID, '
+ 'OwnerName = O.DisplayName, '
+ 'E.LastUpdatedAt, '
+ 'LastUpdatedBy = L.DisplayName, '
+ 'E.LastUpdatedID, '
+ '(Select ModuleTitle from dbo.Modules WHERE ModuleID = E.ModuleID) as ModuleTitle, '
+ 'RMOwnerID = r.OwnerID, '
+ 'r.RRULE, '
+ 'E.OriginalDateBegin, '
+ 'E.NewEventEmailSent '
+ 'FROM dbo.Events E '
+ 'inner join dbo.EventsRecurMaster AS r on E.RecurMasterID = r.RecurMasterID '
+ 'left outer join dbo.Users U on E.CreatedBy = U.UserID '
+ 'left outer join dbo.Users O on E.OwnerID = O.UserID '
+ 'left outer join dbo.Users L on E.LastUpdatedID = L.UserID '
+ 'left join dbo.EventsCategory b on E.Category = b.Category '
+ 'left join dbo.EventsLocation c on E.Location = c.Location '
+ 'WHERE (E.ModuleID = 555 AND E.EventTimeBegin BETWEEN 2012-01-01 AND 2012-12-31) OR ((E.EventTimeBegin <= DATEADD(DAY,1,''' + convert(varchar, #EndDate) + ''') AND DATEADD(minute,E.Duration,E.EventTimeBegin) >= ''' + convert(varchar, #BeginDate) + ''') OR '
+ ' (E.EventTimeBegin BETWEEN ''' + convert(varchar, #BeginDate) + ''' AND DATEADD(DAY,1,''' + convert(varchar, #EndDate) + ''')))'
+ ' AND E.Approved = 1'
+ ' AND E.Cancelled = 0'
+ ' ' + #Filter + ' '
+ ' ORDER BY E.EventDateBegin, E.EventTimeBegin, E.EventDateEnd'
EXEC (#sql)
UPDATE: I used the where statemnnt that Diego recommended but that is not having the desired result. It does not act as and If\Else scanrio (which makes sense when I think about it).
I need to first identify if the module ID is 555 and if so only pull the dates from in the hard coded range otherwise execute it as written. Please let me know if more detail is required.
is the proc failing?
did you try adding E.ModuleID = 555 on the where clause?
Do you really want to hard code the value 555? how about passing it
on a parameter?
And most important question: why adding the sql statement to a
variable and execute it? why not just run the SQL? Is it because of
the #Filter variable?
also, sql server 2005 or 2008?
why nvarchar and not varchar on your variables ("n" occupies double
of space)
EDIT:
ok, you have a OR in there so it may be tricky. Do you want everything from code 555 despite the date range value, or everything within the date range and code 555?
I assume option 2 would make more sense so just add
E.ModuleID = 555
before the
+ ' AND E.Approved = 1'

Correct Amount of Spaces with concatenated person's name in SQL Server

Here is my SQL as I have it now. The first and last name should never be missing because they are required on the interface with validation. However, if the middle initial is missing, I don't want two spaces in the result; I just want one space. I could put a case statement in, but that seems like overkill if SQL already has a function for this purpose. Does anyone know if there is a function for this purpose? What would the code look like?
SELECT ISNULL(contact.firstname, '')
+ ' '
+ ISNULL(contact.middleinitial, '')
+ ' '
+ ISNULL(contact.lastname, '')
FROM dbo.contact
SELECT
ISNULL(contact.firstname, '') +
ISNULL(' ' + contact.middleinitial + ' ', ' ') +
ISNULL(contact.lastname, '')
However, you either should remove ISNULL for firstname, lastname (defined NOT NULL?) or add some trims
SELECT
LTRIM(RTRIM(
ISNULL(contact.firstname, '') +
ISNULL(' ' + contact.middleinitial + ' ', ' ') +
ISNULL(contact.lastname, '')
))
In SQL Server 2012 and up you can use CONCAT function:
SELECT CONCAT(contact.firstname, ' ' + contact.middleinitial, ' ' + contact.lastname)
FROM dbo.contact
If middleinitial is null then appending space to null value will result in null value and CONCAT will skip this null value during concatenation.
SELECT REPLACE(ISNULL(contact.firstname, '') + ' ' + ISNULL(contact.middleinitial, '') + ' ' + ISNULL(contact.lastname, '')
,' ',' ')
FROM dbo.contact

Resources