views:

317

answers:

5

I can write something like this with LINQ:

var selection = from person in personList
                let initials = person.FirstName[0] + person.LastName[0]
                select initials;

Can I do something similar with SQL, like maybe:

SELECT @Initials
FROM [Person]
SET @Initials = SUBSTRING (Person.FirstName, 1, 1) + SUBSTRING (Person.LastName, 1, 1)

Probably not but maybe there is a trick?

I need to have a precalculated variable for further use in a complex WHERE clause to avoid extreme complexity and code repetition.

+3  A: 

A clean way of doing this without adding a temporary table, looping, etc. would be with a Common Table Expression (CTL). Example:

WITH PersonsWithInitials AS (SELECT
     SELECT SUBSTRING (COALESCE(Person.FirstName,''), 1, 1)
        + SUBSTRING (COALESCE(Person.LastName,''), 1, 1) AS Initials,
     FirstName, LastName, City
  FROM [Person]
  );
SELECT FirstName, LastName, City, Initials FROM PersonsWithInitials WHERE
    /* Complex WHERE clause goes here and it can reference Initials as if it were a field */

In place of empty '' above, you could use a period or something else to stand in for null name fields.

This should all be executed in a single SQL call from .NET -- the CTE is not saved in the database like a view, stored procedure, temp table, etc.

richardtallent
would need to test for NULL cases
van
the OP says "I need to have a precalculated variable for further use in a complex WHERE clause". from their question, it looks like they want to store the results in a variable, not just return a one time result set. If not, then this is a good answer, otherwise they need to check out my answer...
KM
-1 this is not what the op is asking if I understand him.
JoshBerke
A: 

What's wrong with:

SELECT SUBSTRING (Person.FirstName, 1, 1) + SUBSTRING (Person.LastName, 1, 1) AS Initials
FROM [Person]
John Saunders
+2  A: 
SELECT Initials
    = SUBSTRING (Person.FirstName, 1, 1)
      + SUBSTRING (Person.LastName, 1, 1)
FROM [Person]

or

SELECT SUBSTRING (Person.FirstName, 1, 1) 
       + SUBSTRING (Person.LastName, 1, 1)
            AS Initials
FROM [Person]

If you need to use it later, a clearly readable way is to use a common table exprssion (which can be stacked, instead of nested):

WITH Person2 AS (
    SELECT SUBSTRING (Person.FirstName, 1, 1) 
           + SUBSTRING (Person.LastName, 1, 1)
                AS Initials
    FROM [Person]
)
SELECT Initials, COUNT(*) AS Record_Count
FROM Person2
GROUP BY Initials
Cade Roux
+3  A: 

Looks like you're just trying to get the initials into a variable for later. Try it this way...

DECLARE @Initials varchar(2)

SELECT @Initials = SUBSTRING (Person.FirstName, 1, 1) + SUBSTRING (Person.LastName, 1, 1)
FROM   [Person]
WHERE  ....

If you're trying to use that as a set and not a single value, you should look at doing a subquery or CTE with your other complex query.

Scott Ivey
A: 

if you want to keep a set of initials to use multiple times, or as part of a larger query, do the following:

declare @TableVariable  table (Initials varchar(200)

INSERT INTO @TableVariable  
        (Initials)
    SELECT
        ISNULL(SUBSTRING(Person.FirstName,1,1),'')+ISNULL(SUBSTRING(Person.LastName,1,1),'')
    FROM Person

SELECT * FROM @TableVariable

SELECT * FROM @TableVariable

if you are doing many rows #temp tables are faster. Also, it would probably be faster to just make this a derived table in a bigger query than using a temp table.

KM
A table variable may drastically hamper performance if the OP's query filters on more than just initials. In most cases, a CTE will be better, since it uses the underlying table's indexes (a table variable does not).
richardtallent
KM