Простой запрос выбора Sql - PullRequest
1 голос
/ 09 апреля 2009

Я знаю, что звучу глупо, но мне очень нужна помощь в этом.

У меня есть таблица (скажем, собрание), которая содержит столбец Участники. Тип данных участников имеет тип varchar (Max) и хранит идентификаторы участников в виде запятой, например 1,2.

Теперь моя проблема в том, что я передаю параметр с именем @ParticipantsID в моей хранимой процедуре и хочу сделать что-то вроде этого:

Select Participants from Meeting where Participants in (@ParticipantsID)

К сожалению, я упускаю что-то важное здесь.

Может кто-нибудь это указать?

Ответы [ 8 ]

3 голосов
/ 09 апреля 2009

Обычно вы не организовали бы свою базу данных SQL таким способом. То, что вы описываете, это две сущности (Встреча и Участник), которые имеют отношение один ко многим. то есть собрание может иметь ноль или более участников. Для моделирования этого в SQL вы должны использовать три таблицы: таблицу собраний, таблицу участников и таблицу MeetingParticipant. Таблица MeetingParticipant содержит связи между собраниями и участниками. Таким образом, вы можете иметь что-то вроде этого (извините за любые ошибки синтаксиса SQL)

create table Meeting
(
  MeetingID int,
  Name varchar(50),
  Location varchar(100)
)

create table Participant
(
  ParticipantID int,
  FirstName varchar(50),
  LastName varchar(50)
)

create table MeetingParticipant
(
  MeetingID int,
  ParticipantID int
)

Чтобы заполнить эти таблицы, вы должны сначала создать участников:

insert into Participant(ParticipantID, FirstName, LastName) values(1, 'Tom', 'Jones')
insert into Participant(ParticipantID, FirstName, LastName) values(2, 'Dick', 'Smith')
insert into Participant(ParticipantID, FirstName, LastName) values(3, 'Harry', 'Windsor')

и создайте собрание или два вставить в Meeting (MeetingID, Name, Location) значения (10, «Обучение SQL», «Комната 1») вставить в Meeting (MeetingID, Name, Location) значения (11, «Обучение SQL», «Комната 2»)

и теперь добавьте некоторых участников к собраниям

insert into MeetingParticipant(MeetingID, ParticipantID) values(10, 1)
insert into MeetingParticipant(MeetingID, ParticipantID) values(10, 2)
insert into MeetingParticipant(MeetingID, ParticipantID) values(11, 2)
insert into MeetingParticipant(MeetingID, ParticipantID) values(11, 3)

Теперь вы можете выбрать все встречи и участников для каждой встречи с помощью

select m.MeetingID, p.ParticipantID, m.Location, p.FirstName, p.LastName
from Meeting m 
  join MeetingParticipant mp on m.MeetingID=mp.MeetingID
  join Participant p on mp.ParticipantID=p.ParticipantID

выше следует произвести

MeetingID ParticipantID Location FirstName LastName
10        1             Room 1   Tom       Jones
10        2             Room 1   Dick      Smith
11        2             Room 2   Dick      Smith
11        3             Room 2   Harry     Windsor    

Если вы хотите узнать все собрания, в которых участвует «Дик Смит», вы напишите что-то вроде этого

select m.MeetingID, m.Location
from Meeting m join MeetingParticipant mp on m.MeetingID=mp.ParticipantID
where
  mp.ParticipantID=2

и получите

MeetingID Location
10        Room 1
11        Room 2

Я пропустил важные вещи, такие как индексы, первичные ключи и пропущенные атрибуты, такие как даты собраний, но это понятнее без всякой липкости

3 голосов
/ 09 апреля 2009

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

Новая функция

IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID(’UF_CSVToTable’))
 DROP FUNCTION UF_CSVToTable
GO

CREATE FUNCTION UF_CSVToTable
(
 @psCSString VARCHAR(8000)
)
RETURNS @otTemp TABLE(sID VARCHAR(20))
AS
BEGIN
 DECLARE @sTemp VARCHAR(10)

 WHILE LEN(@psCSString) > 0
 BEGIN
  SET @sTemp = LEFT(@psCSString, ISNULL(NULLIF(CHARINDEX(',', @psCSString) - 1, -1),
                    LEN(@psCSString)))
  SET @psCSString = SUBSTRING(@psCSString,ISNULL(NULLIF(CHARINDEX(',', @psCSString), 0),
                               LEN(@psCSString)) + 1, LEN(@psCSString))
  INSERT INTO @otTemp VALUES (@sTemp)
 END

RETURN
END
Go

Новый Sproc

 SELECT *
 FROM
  TblJobs
 WHERE
  iCategoryID IN (SELECT * FROM UF_CSVToTable(@sCategoryID))
3 голосов
/ 09 апреля 2009

Ваш стол не нормализован. Если вы хотите сделать запрос об отдельных участниках, они должны быть разбиты на их собственные таблицы, например:

Meeting
    MeetingId primary key
    Other stuff
Persons
    PersonId primary key
    Other stuff
Participants
    MeetingId foreign key Meeting(MeetingId)
    PersonId  foreign key Persons(PersonId)
    primary key MeetingId,PersonId

В противном случае вам придется прибегнуть ко всяким хитростям (то, что я называю гимнастикой SQL), чтобы узнать, чего вы хотите. Эта хитрость никогда не масштабируется хорошо - ваши запросы замедляются очень быстро по мере роста таблицы.

С должным образом нормализованной базой данных запросы могут быстро оставаться в миллионах записей (я работаю с DB2 / z, где мы привыкли к действительно огромным таблицам).

Существуют веские причины иногда возвращаться ко второй нормальной форме (или даже к первой) для повышения производительности, но это должно быть очень сложным решением (и основанным на фактических данных о производительности). Все базы данных должны начинаться с 3NF.

1 голос
/ 09 апреля 2009
SELECT * FROM Meeting WHERE Participants LIKE '%,12,%' OR Participants LIKE '12,%' OR Participants LIKE '%,12'

где 12 - это ID, который вы ищете ....

Ужасно, какая противная модель.

1 голос
/ 09 апреля 2009

Если я правильно понимаю ваш вопрос, вы пытаетесь передать список идентификаторов участников через запятую и посмотреть, есть ли он в вашем списке. Эта ссылка перечисляет несколько способов сделать это "

[http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm][1]

codezy.blogspot.com

0 голосов
/ 09 апреля 2009

Это не лучший способ хранения имеющейся у вас информации.

Если это все, что у вас есть, тогда вам нужно делать содержимое (не IN). Лучший ответ - иметь другую таблицу, которая связывает участников с собраниями.

Попробуйте ВЫБРАТЬ совещание, участники ОТ СОДЕРЖАНИЯ (Участники, @ParticipantId)

0 голосов
/ 09 апреля 2009

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

  • ВСТРЕЧА
    • УЧАСТНИК 1
    • УЧАСТНИК 2
    • УЧАСТНИК 3

Каждый участник будет иметь идентификатор встречи, чтобы вы могли сделать запрос

ВЫБРАТЬ * ОТ участников, ГДЕ meeting_id = 1

Однако, если вам необходимо сохранить список через запятую (по какой-то внешней причине), вы можете выполнить поиск строки, чтобы найти соответствующую запись. Это был бы очень неэффективный способ сделать запрос.

0 голосов
/ 09 апреля 2009

Если вы храните идентификаторы участников в списке через запятую (как текст) в базе данных, вы не можете легко запросить его (как список) с помощью SQL. Вам придется прибегнуть к строковым операциям.

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

create table meeting_participants (
   meeting_id integer not null , -- foreign key
   participant_id integer not null
);

В этой таблице будет несколько строк на одно собрание (по одной для каждого участника). Затем вы можете запросить эту таблицу для отдельных участников или количества участников и т. Д.

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