以下是我的情况的工作流程:
我有一个网站,允许注册用户注册本地奖品赞助商(即:商家)的奖品。例如,可能有一个页面将必胜客作为奖品赞助商,注册/认证用户只需点击“输入图纸”,一旦完成,就无法再次点击它。
以下是3个表格:
BD_Listing(此表适用于奖品赞助商,包括基本栏目,如ListingID,Title,ContactPerson,Email,Prize)
用户(此表适用于网站上的注册用户,包括UserID,FirstName,LastName,Email等)
PrizeEntry(此表是注册人数据的位置:EntryID,ListingID,User_ID,Date_Created)
现在,只要将数据存储在数据库中,这一切都可以正常工作。我的问题是SELECT。我有一个自定义模块,我正在网站的ADMIN端构建,我想执行以下操作:
这是我的查询:
SELECT ListingID, Title, ContactEmail, PrizeSponsor
FROM [BD_Listing]
WHERE PrizeSponsor = 'True'
如果我在网站上的表格中显示此数据,它可以正常工作。问题是,我需要更多数据,特别是PrizeEntry表中的User_ID。此User_ID需要与Users表中的UserID连接,因为我需要从中提取其他信息。
SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor
b.ListingID, b.User_ID
FROM BD_Listing a INNER JOIN PrizeEntry b ON a.ListingID = b.ListingID
WHERE a.PrizeSponsor = 'True'
现在,出现了第一个问题。如果20人注册必胜客,那么我将获得21行数据,这不是我想要的。这里最终是我的代码加入所有信息及其推理,然后你可以告诉我我做错了多么愚蠢:)
SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor
b.ListingID, b.User_ID
c.UserID, c.FirstName, c.LastName, c.Email
,(SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry WHERE (ListingID = a.ListingID)) AS EntryCount
,(SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry WHERE (ListingID = a.ListingID)ORDER BY NEWID()) as RandomWinner
FROM BD_Listing a INNER JOIN PrizeEntry B on a.ListingID = b.ListingID
INNER JOIN Users C on b.User_ID = c.UserID
WHERE a.PrizeSponsor = 'True'
好的,所以在我的表格中显示这些数据我只想让必胜客出现一次,但是因为它与PrizeEntry表一起出现,它会多次出现。
我想看看:
Business: Pizza Hut // comes from the BD_Listing table
Contact: John Doe // comes from the BD_Listing table
Total Registrations: 20 // count from the PrizeEntry table
Random Winner: John Smith (UserID:10) // result from the subquery
但相反,每次注册奖品时,我都会看到每个商家有多行。
我道歉......我是新来的,这是我的第二篇文章。并通过SQL的开始学习曲线。
非常感谢您的任何建议。
答案 0 :(得分:1)
首先,如果有20个用户,则应该有20行,而不是21行。
我认为您可以简化查询,只需删除外部联接给用户,即可获得所需内容:
SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor,
(SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID)) AS EntryCount,
(SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID) ORDER BY NEWID()) as RandomWinner
FROM BD_Listing a
WHERE a.PrizeSponsor = 'True'
您想获得赞助商的信息。相关子查询获取附加信息。要获得有关获胜者的更多信息,只需将其作为子查询并加入相应的表格,如下所示:
with t as (
SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor,
(SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID)) AS EntryCount,
(SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID) ORDER BY NEWID()) as RandomWinner
FROM BD_Listing a
WHERE a.PrizeSponsor = 'True'
)
select t.*, u.Firstname, u.LastName, u.Email
from t join
users u
on t.RandomWinner = u.user_id
答案 1 :(得分:0)
最简单的方法是两个做两个查询。第一个获取赞助商信息,第二个查询获取条目。
从技术上讲,这是N + 1的情况(参见:What is SELECT N+1?),但我不会在此担心。
理论上你可以立刻得到所有东西,然后在前端你循环通过它,看看你是否已经打印了赞助商。问题在于,做N + 1实际上要好得多。
现在,如果您想要有关赞助商的摘要信息,那么您可以使用GROUP BY
声明进行此操作。
像这样:
SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, COUNT(*) AS EntryCount
FROM BD_Listing a INNER JOIN PrizeEntry B on a.ListingID = b.ListingID
INNER JOIN Users C on b.User_ID = c.UserID
WHERE a.PrizeSponsor = 'True'
GROUP BY a.ListingID
答案 2 :(得分:0)
由于你的联接结构,你将得到所有匹配的组合:因为事情就是你无法得到任何其他东西。
您需要做的是先获取参赛者并确定您的获胜者,然后将其与列表相关联:
select a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, d.userid, d.firstname, d.lastname, d.email
from BD_Listing a inner join (
select top 1 listingid, userid, firstname, lastname, email from (
select b.ListingID, c.UserID, c.FirstName, c.LastName, c.Email, newid() as ordering
from PrizeEntry B INNER JOIN Users C on b.User_ID = c.UserID
) x order by ordering
) d on a.listingid = d.listingid