在一个查询中两次从同一个表中提取时出现问题
Posted
技术标签:
【中文标题】在一个查询中两次从同一个表中提取时出现问题【英文标题】:Trouble pulling from the same table twice in one query 【发布时间】:2021-03-05 17:05:56 【问题描述】:对不起,如果这个标题措辞奇怪。我正在处理一个查询,该查询会提取在某个地方拥有会员资格的人员列表。该查询从Demographics
表中提取一些人口统计信息,并从Visit
表中提取上次/下一次访问日期。即使某个人不再是会员,他们仍会保留在系统中,但他们的帐户会被标记为“已转移”标记(以 varchar 格式)。我需要能够在系统中提取 所有 成员的列表,但有一个列显示给定成员是否具有转移标志。标志字段也可以在Demographics
表中找到,并且成员可以拥有许多不同的标志。一个成员可能有 10 个不同的标志。
在我的脑海中,直接的解决方案是查询Demographics
表两次,第一个实例显示每个成员的实际人口统计数据,第二个实例显示转移的标志。查询运行没有错误;但是,它最终仍然显示仅转移的成员,我意识到我使用的逻辑不太合理。我认为我在正确的轨道上,但需要解决这个问题。
这是我的查询:
SELECT DISTINCT
d.MemberID,
d.MemberName,
d.DateOfBirth,
[a few other demographic fields blah blah],
v.LastVisitDate,
v.NextVisitDate,
d2.MemberFlag as [Transferred?]
FROM Demographic d JOIN Visit v ON d.MemberID = v.MemberID
JOIN Demographic d2 ON d.MemberID = d2.MemberID
WHERE d2.MemberFlag LIKE '%transf%'
我尝试了不同类型的JOINs
,但没有任何效果,但就像我说的,我意识到我的逻辑有点不对劲。我觉得解决方案可能会变得非常简单,但我的大脑无法正常工作。这是我希望实现的目标:
MemberID MemberName ... NextVisitDate Transferred?
------------------------------------------------------------------
1001 John Smith ... 03/10/2021
1002 Jane Doe ... NULL Transferred
1003 Bob Brown ... 04/22/2021
1004 Mike Jones ... 03/17/2021
1005 Ann Green ... 03/30/2021
1006 Dan White ... NULL Transferred
★★更新★★
我找到了解决方案...我决定尝试在原始Demographics
表中仅使用带有标志字段的CASE
,而不是再次尝试查询该表。
SELECT DISTINCT
d.MemberID,
d.MemberName,
d.DateOfBirth,
[a few other demographic fields blah blah],
v.LastVisitDate,
v.NextVisitDate,
(CASE
WHEN d.MemberFlag LIKE '%transf%' THEN 'Transferred'
ELSE ''
END) AS [Transferred?]
FROM Demographic d JOIN Visit v ON d.MemberID = v.MemberID
这几乎完美运行。我仍然遇到一个小问题,即任何拥有已转移标志的成员最终也会出现带有空白标志字段的行,所以就像那些人在重复一样。结果现在最终如下所示。关于如何避免这种情况的任何想法?
MemberID MemberName ... NextVisitDate Transferred?
------------------------------------------------------------------
1001 John Smith ... 03/10/2021
1002 Jane Doe ... NULL
1002 Jane Doe ... NULL Transferred
1003 Bob Brown ... 04/22/2021
1004 Mike Jones ... 03/17/2021
1005 Ann Green ... 03/30/2021
1006 Dan White ... NULL
1006 Dan White ... NULL Transferred
【问题讨论】:
提示:SELECT DISTINCT
通常是一种代码异味,因为这意味着您正在删除原本不应该重复的数据。那么,为什么你使用SELECT DISTINCT
?
@Dai 老实说,这只是一种习惯,因为我必须使用的数据库结构很糟糕,如果我不使用SELECT DISTINCT
,一半的时间,我得到一堆重复的结果。但这与我要问的问题有什么关系吗?
好吧,你说你遇到了问题并且我看到你正在使用 select-distinct - 我认为它是相关的。
好吧,我刚刚删除了 DISTINCT
部分并再次对其进行了测试——这个简单的查询现在需要 几分钟 才能运行,而截至这一秒,还没有结束。暂时忽略这个问题,你还有其他想法吗?我原来的逻辑是否正确?
【参考方案1】:
我同意,您在人口统计表中的成员 ID、姓名和出生日期看起来像重复数据,每个数据表包含多行。不酷,但如果你有的话。
如果“MemberID”是唯一 ID,并且成员的姓名和出生日期在每一行都相同,那么您可以通过 memberID 应用一个组,然后在所有您想要的字段上执行 MAX()改变。例如:如果我的出生日期是 2000 年 3 月 5 日,并且我有 10 条记录,我的出生日期都是 2020 年 3 月 5 日,那么 MAX(d.DateOfBirth) 仍然会产生 3 月 5 日。所以考虑到这个前提,这个查询可能有助于获得您要查找的内容。
SELECT
d.MemberID,
max( d.MemberName ) MemberName,
max( d.DateOfBirth ) DateOfBirth,
max( each other blah blah fields) blahField1,
coalesce( max( v.LastVisitDate ), '' ) LastVisitDate,
coalesce( max( v.NextVisitDate ), '' ) NextVisitDate,
max( CASE WHEN d.MemberFlag LIKE '%transf%' THEN 'Transferred'
ELSE ''
END) AS Transferred
from
Demographic d
JOIN Visit v
ON d.MemberID = v.MemberID
group by
d.MemberID
【讨论】:
【参考方案2】:您可以使用 CTE 拉出转移的标志,然后左连接到它。
with transferred as
(
select distinct MemberID, 'Y' as transfer_flag
from demographic
where MemberFlag like '%transf%'
)
select distinct
d.MemberID,
d.MemberName,
d.DateOfBirth,
v.LastVisitDate,
v.NextVisitDate,
t.transfer_flag
from demographic d
join visit v
on v.MemberID = v.MemberID
left join transferred t
on t.MemberID = d.MemberID
在 sql-server 中,它可能看起来有点不同。我没有用过那个 dbms,但它可能看起来像这样......
with transferred (MemberID, transfer_flag)
as
(
select distinct MemberID, 'Y'
from demographic
where MemberFlag like '%transf%'
)
select distinct
d.MemberID,
d.MemberName,
d.DateOfBirth,
v.LastVisitDate,
v.NextVisitDate,
t.transfer_flag
from demographic d
join visit v
on v.MemberID = v.MemberID
left join transferred t
on t.MemberID = d.MemberID
【讨论】:
以上是关于在一个查询中两次从同一个表中提取时出现问题的主要内容,如果未能解决你的问题,请参考以下文章