我需要向系统显示所有输入日期范围的客户。 所有客户都被分配到一个组,但不一定分配给员工。
当我按原样运行查询时:
SELECT
clients.name_lastfirst_cs,
to_char (clients.date_intake,'MM/DD/YY')AS Date_Created,
clients.client_id,
clients.display_intake,
staff.staff_name_cs,
groups.name
FROM
public.clients,
public.groups,
public.staff,
public.link_group
WHERE
clients.zrud_staff = staff.zzud_staff AND
clients.zzud_client = link_group.zrud_client AND
groups.zzud_group = link_group.zrud_group AND
clients.date_intake BETWEEN (now() - '8 days'::interval)::timestamp AND now()
ORDER BY
groups.name ASC,
clients.client_id ASC,
staff.staff_name_cs ASC
我得到121个条目
如果我发表评论:
SELECT
clients.name_lastfirst_cs,
to_char (clients.date_intake,'MM/DD/YY')AS Date_Created,
clients.client_id,
clients.display_intake,
-- staff.staff_name_cs, -- Line Commented out
groups.name
FROM
public.clients,
public.groups,
public.staff,
public.link_group
WHERE
-- clients.zrud_staff = staff.zzud_staff AND --Line commented out
clients.zzud_client = link_group.zrud_client AND
groups.zzud_group = link_group.zrud_group AND
clients.date_intake BETWEEN (now() - '8 days'::interval)::timestamp AND now()
ORDER BY
groups.name ASC,
clients.client_id ASC,
staff.staff_name_cs ASC
我得到173个条目
我知道我需要做一个外部联接来捕获所有客户端,无论是否存在 是指派的工作人员,但每次尝试都失败了。我已经完成了外连接 两张桌子,但加上三分之一已经扭曲了我的大脑。
感谢您的任何建议
答案 0 :(得分:1)
我无法对此进行测试(或知道它是正确的),但我在您的查询中读到的是您想要类似于此的内容:
SELECT --I just used short aliases. I choose something other than the table name so I know it is an alias "c" for client etc...
c.name_lastfirst_cs,
to_char (c.date_intake,'MM/DD/YY')AS Date_Created,
c.client_id,
c.display_intake,
s.staff_name_cs,
g.name,
l.zrud_client AS "link_client",--I'm selecting some data here so that I can debug later, you can just filter this out with another select if you need to
l.zzud_group AS "link_group" --Again, so I can see these relationships
FROM
public.clients c
LEFT OUTER JOIN staff s ON --is staff required? If it isn't then outer join (optional)
s.zzud_staff = c.zrud_staff --so we linked staff to clients here
LEFT OUTER JOIN public.link_group l ON --this looks like a lookup table to me so we select the lookup record
l.zrud_client = c.zzud_client -- this is how I define the lookup, a client id
LEFT OUTER JOIN public.groups g ON --then we use that to lookup a group
g.zzup_group = l.zrud_group --which is defined by this data here
WHERE -- the following must be true
c.date_intake BETWEEN (now() - '8 days'::interval)::timestamp AND now()
现在为什么:我基本上将你的where子句移动到JOIN x ON y=z
语法。根据我的经验,这是编写维护查询的更好方法,因为它允许您指定表之间的关系,而不是执行大型连接并尝试使用where子句过滤该数据。请记住,每个条件都是必需的,而不是可选的,所以当你说你想要具有以下条件的记录时,你就会得到它们(如果我读得正确的话 - 我可能不会因为我没有架构我的前面)如果记录缺少链接表记录或工作人员你要过滤掉它。
或者(可能明显更慢)你可以选择任何东西,这样你就可以把它链接起来:
SELECT
*
FROM
(
SELECT
*
FROM
public.clients
WHERE
x condition
)
WHERE
y condition
OR
SELECT * FROM x WHERE x.condition IN (SELECT * FROM y)
在您的情况下,这种策略可能不会比标准的连接语法更容易。
^这里有一些认真的意见:我建议你使用我在上面概述的连接语法。它在功能上与连接和指定where子句相同,但正如您所指出的,如果您不理解它们可能导致笛卡尔连接的关系。 http://www.tutorialspoint.com/sql/sql-cartesian-joins.htm。最后,我倾向于指定我想要的连接类型。我在查询中写了很多INNER JOIN
和OUTER JOIN
因为它有助于下一个人(通常是我)弄清楚我的意思。如果是可选的,则使用外部联接,如果需要,则使用内部联接(默认)。