SQL Server: оператор OR внутри оператора CASE - PullRequest
0 голосов
/ 23 мая 2018

У меня есть хранимая процедура, которая запрашивает некоторые записи сотрудников, основываясь на том, что отправил пользователь.

В пользовательском интерфейсе пользователь вводит несколько точек данных, таких как адреса электронной почты, идентификаторы пользователей или имена сотрудников.Эта хранимая процедура проверяет, какой тип данных они предоставляют, и затем ищет в этом поле записи в базе данных.

Входные данные для хранимой процедуры:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <data>
      <dataPoints>
         <dataPoint>
            <order>0</order>
            <value>Jim Bob</value>
         </dataPoint>
         <dataPoint>
            <order>1</order>
            <value>Sally Jones</value>
         </dataPoint>
      </dataPoints>
   </data>
</root>

Запрос:

    @dataType VARCHAR (20), @data XML
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN

    -- Create a temp table 
    DECLARE @dataSet TABLE (data VARCHAR(100), [order] INT);

    INSERT INTO @dataSet( data , [order] )
        SELECT  
            ParamValues.x1.value('value[1]', 'VARCHAR(100)') ,
            ParamValues.x1.value('order[1]', 'INT') 
        FROM 
            @data.nodes('/root/data/dataPoints/dataPoint') AS ParamValues(x1)

    -- Search Employees
    SELECT 
        ec.FirstName, ec.PreferredName, ec.LastName,
        ec.NTID, ec.QID,
        ec.DepartmentName, ec.SegmentName,
        ec.CenterName, ec.RoleName, ec.MarketName,
        ec.IncentivePlanName,
        ec.CostCenterID,
        ec.SupFirstName, ec.SupPreferredName, ec.SupLastName,
        ec.SiloName,
        ec.AreaName,
        ec.PersonnelID,
        d.[order]
    FROM
        Resources.emp.EmployeeComplete AS ec
    INNER JOIN
        @dataset AS d ON d.data = CASE 
                                     WHEN @dataType = 'NTID' THEN ec.ntid 
                                     WHEN @dataType = 'QID' THEN ec.QID 
                                     WHEN @dataType = 'Emp ID' THEN ec.EmpID 
                                     WHEN @dataType = 'Email Address' THEN ec.Email 
                                     WHEN @dataType = 'Personnel ID' OR @dataType = 'Sap ID' THEN ec.PersonnelID 
                                     --WHEN @dataType = 'Name' THEN (
                                     -- (ec.FirstName + ' ' + ec.LastName) 
                                     --     OR (ec.PreferredName + ' ' + ec.LastName)
                                     --     OR (ec.LastName + ', ' + ec.FirstName)
                                     --     OR (ec.LastName + ', ' + ec.PreferredName
                                     -- )
                        END
    FOR XML PATH ('employees'), ELEMENTS, TYPE, ROOT ('root');

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

Проблема / вопрос:

Вы увидите, что у меня есть закомментированный код вмой пример, и это где моя проблема.В моей базе данных есть три поля имени.First Name, Preferred Name, Last Name.

Мне необходимо проверить, что предоставил пользователь, и найти сотрудников на основе введенной им комбинации.Все, что пользователь выбирает в пользовательском интерфейсе, это то, что он предоставляет имя, но не формат, в котором оно находится.

По этой причине мне нужно проверить, могу ли я найти записи в паре разных форматов.

В этом случае проблема заключается в том, что я не могу присоединиться к своему набору данных, используя условия OR в выражении CASE.

Если @dataType = 'Name', мне нужно иметь возможность присоединиться к своемувременная таблица на пару различных комбинационных возможностей.

Единственное, о чем мы узнаем, это то, что они не могут смешиваться и сочетаться.Это означает, что они не могут FirstName LastName выполнить поиск LastName FirstName.

У меня возникли проблемы с объяснением этого, поэтому, пожалуйста, дайте мне знать, если мне нужно как-то уточнить.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

А как насчет того, чтобы просто добавить OR в ваше объединение?

FROM    @dataset AS d
        INNER JOIN Resources.emp.EmployeeComplete AS ec
        ON (@dataType = 'NTID' AND ec.ntid = d.data)
            OR (@dataType = 'QID' AND ec.QID = d.data)
            OR (@dataType = 'Emp ID' AND ec.EmpID = d.data)
            OR (@dataType = 'Email Address' AND ec.Email = d.data)
            OR ((@dataType = 'Personnel ID' OR @dataType = 'Sap ID') AND ec.PersonnelID = d.data)
            OR (@dataType = 'Name' AND (ec.FirstName + ' ' + ec.LastName) = d.data)
            OR (@dataType = 'Name' AND (ec.PreferredName + ' ' + ec.LastName) = d.data)
            OR (@dataType = 'Name' AND (ec.LastName + ', ' + ec.FirstName) = d.data)
            OR (@dataType = 'Name' AND (ec.LastName + ', ' + ec.PreferredName) = d.data)

Я не уверен, достаточно ли умен SQL, чтобы использовать правильные индексы в этих полях, если они у вас есть, вероятно, особенно не при объединении столбцов,Вы должны создать индексированные представления для этих объединенных имен или вычисляемых столбцов, по которым можно индексировать.Может быть, лучше разбить их на отдельные запросы в if / thens, чтобы SQL мог оптимизировать каждый запрос на основе поля, к которому вы присоединяетесь, и просто выполнить один запрос.

0 голосов
/ 23 мая 2018

Нажмите уравнения в CASE.Если они верны, пусть THEN вернет 1. Проверьте, вернул ли CASE 1. Если и только если это так, вы нашли совпадение.В условиях WHEN вы можете использовать логические операторы.Таким образом, вы можете создать свой OR (или использовать IN, как я делал ниже).

...
CASE 
WHEN @dataType = 'NTID' AND d.data = ec.ntid THEN 1
WHEN @dataType = 'QID' AND d.data = ec.QID THEN 1
...
WHEN (@dataType = 'Personnel ID' OR @dataType = 'Sap ID') AND d.data = ec.PersonnelID THEN 1
WHEN @dataType = 'Name' AND (d.data IN ('' + ec.FirstName + ' ' + ec.LastName, 
                                        '' + ec.PreferredName + ' ' + ec.LastName,
                                        '' + ec.LastName + ', ' + ec.FirstName,
                                        '' + ec.LastName + ', ' + ec.PreferredName) THEN 1
END = 1
...
...