Оператор условного выбора SQL-сервера - PullRequest
1 голос
/ 18 февраля 2010

Хорошо, это может быть легко, но я просто не могу понять.

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

Пример:

Я пользователь, который ищет следующие элементы, я ввожу по крайней мере один и до 4 элементов ниже в текстовое поле: Имя, возраст, пол, вес (пользователь может или не может заполнить все из них).

Если он просто введет "F" для обозначения пола, он получит список тысяч женщин с указанием их имени, возраста, пола и веса.

Однако, если он введет «F» для пола и «300» для веса, он получит гораздо меньший список возвращаемых записей.

Мне нужно иметь возможность создавать оператор SQL, который может выполнять этот поиск с этой функциональностью.

advTHANKSance

Ответы [ 6 ]

4 голосов
/ 18 февраля 2010

Я часто видел, как это делается с помощью следующего оператора SQL (где @gender, @weight, @age и @name заполнены данными пользователя, а gender, weight , age и name - поля таблицы):

SELECT * FROM MyTable
WHERE
    gender = COALESCE(@gender, gender)
    AND weight = COALESCE(@weight, weight)
    AND age = COALESCE(@age, age)
    and name= COALESCE(@name, name)

( Редактировать : я просто хотел добавить краткое объяснение того, почему это работает для тех, кто не знаком с coalesce. Функция coalesce принимает первое ненулевое значение из 2, переданное в Таким образом, если в параметре @ есть что-то, что означает, что пользователь ввел данные для этого поля, он проверит, равно ли поле тому введенному пользователем значению, если пользователь ничего не вводил и параметр @ имеет значение null, оно будет проверяться по второму значению, которое является самим полем - и так как поле всегда равно самому себе, оно возвратит все записи - оно не будет фильтровать на основе этого поля вообще.)

4 голосов
/ 18 февраля 2010

Я использовал аналогичный приведенный ниже, чтобы сделать то, что вы пытаетесь:

DECLARE @Gender varchar(1)
DECLARE @Age int
DECLARE @Weight int
DECLARE @Name varchar(64)

 SELECT * FROM MyTable
    WHERE
    (@Gender is null OR Gender = @gender)
    AND (@weight is null OR Weight = @weight)
    AND (@Age is null OR  age = @Age)
    and (@Name is null OR Name = @Name)

если бы вы создали хранимую процедуру (которую я бы порекомендовал), она бы выглядела так:

CREATE PROCEDURE SelectRecords
    @Gender varchar(1),
    @Age int,
    @Weight int,
    @Name varchar(64)
AS
     SELECT * FROM MyTable
        WHERE
        (@Gender is null OR Gender = @gender)
        AND (@weight is null OR Weight = @weight)
        AND (@Age is null OR  age = @Age)
        and (@Name is null OR Name = @Name)

То, что делает эта хранимая процедура, проверяет, передали ли вы значение для определенного параметра. Если вы не сделали этого, то он будет нулевым, и условие будет истинным. если вы DID, то оно не будет нулевым, и второе условие должно иметь значение true для записи, которая будет возвращена.

1 голос
/ 26 февраля 2010

@ Abe - Ваше решение будет работать, ЕСЛИ возраст и вес не указаны между именем и полом в выражении SELECT. Я знаю, потому что я попробовал это :) на SQL Server 2008. Я сделал таблицу со многими записями с NULL, разбросанными по всему. Я также сделал процедуру, и запуск ее, как вы написали, не будет возвращать строки, когда в качестве параметров были введены возраст или вес. Я переместил основанные на int параметры в инструкции SELECT в начало или конец списка, оба сработали. Но вложение параметров int между строковыми параметрами в операторе select и последующее указание параметров int приводило к сбою ...

Так почему же оригинал не работал ?? :) Кто-нибудь?

Кстати, COALESCE не будет работать вообще (да, я проверил это и переупорядочил оператор SELECT в процедуре). Выглядело так, как будто должно работать ...

1 голос
/ 18 февраля 2010

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

CREATE myFunnyProc ( @p1 nvarchar(10), @p2 nvarchar(10) ) AS BEGIN
    SELECT * FROM dbo.myReallyLongTable table
    WHERE
             (@p1 is null or table.name LIKE @p1) 
        AND  (@p2 is null or table.age  = @p2)

END
0 голосов
/ 18 февраля 2010

Ответом является то, что большинство людей стараются держаться подальше от него, это динамический sql.

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

Declare 
    @gender varchar(1),
    @weight int,
    @age int,
    @name varchar(100), 
    @sql varchar(200),
    @variableCount int

set @variableCount = 0 

set @sql = 'select * from tablename'

if(@gender is not null)
Begin
@sql += ' where gender = @gender'
@vaiableCount = @VariableCount+1
End

if(@weight is not null)
Begin
if(@variableCount = 0)
Begin
@sql += ' Where ' 
End 
else 
@sql += ' And '
@sql += 'weight = @weight'
End

if(@age is not null)
Begin
if(@VariableCount = 0)
Begin
@sql += ' where '
End
else 
@sql += ' And '
@sql += 'age = @age'
End

if(@name is not null)
Begin
if(@VariableCount = 0)
Begin
@sql += ' where '
End
else 
@sql += ' And '
@sql += 'name = @name' 
End

execute @sql 
0 голосов
/ 18 февраля 2010

Поскольку вы используете ASP.NET, вы можете взглянуть на LINQ-to-SQL, который решает эту проблему очень элегантно:

var query = db.T_Persons;
if (txtGender.Text != string.Empty)
    query = query.Where(x => x.Gender == txtGender.Text);
if (txtWeigth.Text != string.Empty)
    query = query.Where(x => x.Weight == int.Parse(txtWeight.Text));
...

Конечно, вам нужно использовать .NET 3.5 или новее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...