Могу ли я определить переменную цикла в T-SQL SELECT (например, LET в LINQ)?

Я могу написать что-то вроде LINQ:

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

Можно ли сделать что-то подобное с SQL, например:

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

Возможно, нет, но может быть, есть трюк?

Мне нужно иметь предварительно просчитанную переменную для дальнейшего использования в сложном предложении WHERE, чтобы избежать чрезмерной сложности и повторения кода.

Ответ 1

Чистый способ сделать это без добавления временной таблицы, цикла и т.д. будет с помощью Common Table Expression (CTE). Пример:

;WITH PersonsWithInitials AS
(
    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 */

Вместо пустой '' вы можете использовать период или что-то еще, чтобы стоять за полями с нулевым именем.

Все это должно выполняться в одном вызове SQL из .NET. CTE не сохраняется в базе данных, как представление, хранимая процедура, временная таблица и т.д.

Ответ 2

Похоже, вы просто пытаетесь получить инициализацию в переменной позже. Попробуйте это так...

DECLARE @Initials varchar(2)

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

Если вы пытаетесь использовать это как набор, а не одно значение, вы должны посмотреть на выполнение подзапроса или CTE с помощью другого сложного запроса.

Ответ 3

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

или

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

Если вам нужно использовать его позже, ясно читаемым способом является использование общей таблицы exprssion (которая может быть сложена, а не вложенной):

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

Ответ 4

если вы хотите, чтобы ряд инициалов использовался несколько раз или как часть более крупного запроса, выполните следующие действия:

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

если вы делаете много строк #temp-таблицы быстрее. Кроме того, вероятно, было бы быстрее просто сделать эту производную таблицу более крупным запросом, чем использовать временную таблицу.