一个简单的SQL选择查询

时间:2009-04-09 05:18:45

标签: sql sql-server tsql

我知道我听起来很蠢,但我真的需要帮助。

我有一个表(比如说会议),其中包含一个列参与者。 参与者dataType是varchar(Max),它以逗号分隔的形式存储参与者的ID,如1,2。

现在我的问题是我在我的存储过程中传递了一个名为@ParticipantsID的参数,并希望这样做:

Select Participants from Meeting where Participants in (@ParticipantsID)

不幸的是,我在这里缺少一些至关重要的东西。

有人能说出来吗?

8 个答案:

答案 0 :(得分:3)

我以前去过那里......我改变了数据库设计,让一条记录包含对另一个表的单一引用。如果你无法改变你的数据库结构,你必须忍受这个,我在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))

答案 1 :(得分:3)

您的表格未正常化。如果要查询单个参与者,则应将它们拆分为自己的表格,如下所示:

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开始。

答案 2 :(得分:3)

您通常不会以这种方式组织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')

并创建一两个会议     插入会议(MeetingID,名称,位置)值(10,'SQL培训','房间1')     插入会议(MeetingID,名称,位置)值(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

我省略了重要的事情,比如索引,主键和缺少的属性,例如会议日期,但没有所有的goo就更清楚了。

答案 3 :(得分:1)

如果我正确理解您的问题,您正在尝试传入逗号分隔的参与者ID列表,并查看它是否在您的列表中。这个链接列出了几种做这种事情的方法“

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

codezy.blogspot.com

答案 4 :(得分:1)

SELECT * FROM Meeting WHERE Participants LIKE '%,12,%' OR Participants LIKE '12,%' OR Participants LIKE '%,12'

其中12是您要找的ID ....

丑陋,多么讨厌的模特。

答案 5 :(得分:0)

如果将参与者ID存储在数据库中以逗号分隔的列表(作为文本)中,则无法使用SQL轻松查询(作为列表)。你不得不求助于字符串操作。

您应该考虑更改架构以使用另一个表将会议映射到参与者:

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

该表每次会议将有多行(每个参与者一个)。 然后,您可以查询该表以查找单个参与者或参与者数量等。

答案 6 :(得分:0)

如果参与者是单独的数据类型,则应将其存储为会议桌的子表。 e.g。

  • MEETING
    • 参与者1
    • 参与者2
    • 参与者3

每个参与者都会保留会议ID,以便您进行查询

SELECT * FROM参与者WHERE meeting_id = 1

但是,如果必须存储以逗号分隔的列表(出于某些外部原因),则可以执行字符串搜索以查找相应的记录。这可能是一种非常低效的查询方式。

答案 7 :(得分:0)

这不是存储您所拥有信息的最佳方式。

如果这就是你所拥有的那么你需要做一个包含(不是IN)。最好的答案是建立另一个将参与者与会议联系起来的表格。

尝试SELECT会议,来自会议CONTAINS的参与者(参与者,@ PrentantId)