【问题标题】:Getting all data from multiple JOINS从多个 JOINS 中获取所有数据
【发布时间】:2012-11-23 20:56:35
【问题描述】:

我在这里要做的是通过选择工作然后选择要搜索的标签来获取所有已申请某项工作或已被标记为某项工作的申请人。这是我正在使用的 sql 语句。

SELECT ap.user_id, ap.job_id as jobId, date(app_date) AS appDate, count(*) AS `count`   ,jt.name AS title, a.*, ap.app_id
FROM applications ap
LEFT JOIN jobs j ON ap.job_id = j.job_id
LEFT JOIN job_titles jt ON jt.name = j.title
LEFT JOIN applicants a ON a.applicant_id = ap.user_id
LEFT JOIN applicant_tags at ON at.applicant_id = ap.user_id
LEFT JOIN tags t ON t.id = at.tag_id
WHERE ap.favorite = 1
AND LOWER(jt.name) = LOWER('fisherman')
AND (LOWER(t.name) = LOWER('confident')
OR LOWER(t.name) = LOWER('hard worker'))
GROUP BY ap.app_id
HAVING `count` = '2'
ORDER BY jt.name

我的问题是,我只收到申请了该工作的申请人,而不是那些被标记为该类型工作的申请人。职位名称本身不存储为标签,而是通过如下所示的申请者标签表链接到每个申请人:

applicant_id | tag_id | job_id
34                0        4
34                4        0
34                0        5
32                7        0

申请人id通过应用程序user_id链接到应用程序,tag_id通过标签id链接到应用程序,job_id通过job_titles id链接到应用程序。 tags 表和 job_titles 表中只有一个 id 和 name。

这是标签表:

id | tag_id

job_titles 表:

id | name

申请人拥有申请人的所有个人信息(电子邮件、电话号码)以及用作外键的申请人id。

应用程序和作业有太多信息无法列出,实际使用的只有几列。

应用程序表

app_id | user_id | job_id | app_date | favorites .....

工作表

job_id | title | location | jobtype .....

如果申请人有 job_id,则 tag_id 为 0,反之亦然。标签名称和工作名称不存储为逗号分隔值,而是存储为一行中的单个值,该值通过其申请者 ID 链接到每个申请人。 jobs中的job_id是申请的职位id,不是职位名称。每个申请人可以有多个与其关联的标签和多个与其关联的职位名称。标签语句 LOWER(t.name) = LOWER(tag name) 是根据搜索中使用的标签数量添加的。我从申请者那里得到所有信息,因为这些信息以及申请中调用的内容将显示在页面上。

应用程序 ap 通过 ap.job_id 链接到工作,通过 ap.applicant_id = at.applicant_id 链接到申请者标签,通过 ap.applicant_id = a.applicant_id 链接申请者。

job_titles jt 通过 jt.name = j.title 链接到工作 j 并通过 j.id = at.job_id 链接到 application_tags

标签 t 通过 t.id = at.tag_id 链接到申请者标签处

我也不能使用聚合表。

那么,我如何才能获取链接到职位名称的申请,而不是从jobs 表到job_titles 表,而是从application_tags 表到job_titles 表?

-编辑

重构我的 sql 语句后,我可以将它显示到它显示所有申请人但不显示任何标签的位置,如果我尝试搜索任何标签,它不会返回任何结果。

SELECT ap.user_id, jt.id as jobId, date(app_date) AS appDate, jt.name AS title,   count(*) AS `count`, at.*, a.*, ap.app_id, t.*    
FROM applications ap                                 
INNER JOIN applicants a ON ap.user_id = a.applicant_id
LEFT JOIN applicant_tags at ON at.applicant_id = a.applicant_id
LEFT JOIN tags t ON at.tag_id = t.id
LEFT JOIN job_titles jt ON at.job_id = jt.id
WHERE ap.favorite = '1'
AND LOWER(jt.name) = LOWER('fisherman')
GROUP BY ap.app_id
HAVING `count` = '1'
ORDER BY jt.name

【问题讨论】:

  • group by 怎么了?我什至没有看到在查询中调用它。按照标准,您不应该在聚合功能之前对所有项目进行分组吗? (Count (*)) 我知道这并不是在所有情况下都是正确的,但我会先检查一下
  • 刚刚添加了缺少的 HAVING 子句,group by 用于去除重复的应用程序。
  • 这不会消除重复,如果有 2 个,它只会返回记录,它们仍然可能是相同的。
  • 您实际上是在尝试运行 2 个不同的查询。最好使用UNIONUNION ALLSELECT applicant_id, 0 AS tag_id, job_id FROM ...query about applied job... UNION ALL SELECT applicant_id, tag_id, 0 AS job_id FROM ...query about tagged... 来完成。不幸的是,关于您的表关系的信息太少,我无法为您提供完整的查询。

标签: php mysql relational-database foreign-key-relationship


【解决方案1】:

我会看看嵌套查询,在另一个说明中......这可以在下面找到...... http://www.felixgers.de/teaching/sql/sql_nested_queries.html

对于这个查询,如果您将所有申请人信息打包到一个汇总表中会更容易。然后将作业 id 的东西加入另一个表,或者使用原始的,适当地添加索引,这样它就不会超时,然后繁荣......容易得多。

SELECT ap.user_id, ap.job_id as jobId, date(app_date) AS appDate, count(*) AS `count` ,jt.name AS title, `a.*` -- a.* is this necessary? It would help if you were explicit
FROM applications ap
LEFT JOIN jobs j ON ap.job_id = j.job_id --take all items from applications and puta  jobid to them
LEFT JOIN job_titles jt ON jt.name = j.title -- now you are trying to add a title to job from ANOTHER table while retaining all records from applications
LEFT JOIN applicants a ON a.applicant_id = ap.user_id --then you want the applicant that matches the criteria to each application record
LEFT JOIN applicant_tags at ON at.applicant_id = ap.user_id
LEFT JOIN tags t ON t.id = at.tag_id
WHERE ap.favorite = 1
AND LOWER(jt.name) = LOWER('fisherman')
AND (LOWER(t.name) = LOWER('confident')
OR LOWER(t.name) = LOWER('hard worker')) 
GROUP BY ap.app_id -- how are you grouping by something that is not being called?
HAVING `count` = '2' -- They need to have two records, does not matter if they are the same
ORDER BY jt.name -- This is fine

好吧,除了我的 cmets,这实际上是合法的。但是,我会创建一个申请人信息的聚合表,然后在该表上进行一次连接,以使事情变得更容易

看起来您正在使用的表是:

应用程序 加入 符合条件的申请人

内连接这些表

Applicants_tags 与标签加入 sample_tags 标签 工作——加入这个 工作表的job_titles

【讨论】:

  • 很遗憾,我无法创建两者的聚合表。我还需要申请人提供的所有内容,因为这是页面上显示的大部分内容。
  • 你应该在你的问题中包含这个......为什么你不能使用聚合?
  • 这样做需要我重做整个网站上的几乎每个页面,并且我不能修改任何一个表中的任何数据。
  • 那么您使用的是什么数据库?聚合很漂亮,因为它们不必与任何东西联系起来......如果你想开始聊天,我们可以......
  • InnoDB 用于应用程序,MyISAM 用于其他一切。这个网站经历了很多不同的人,所以一切都非常不一致。
【解决方案2】:

我发现了怎么做。我不得不使用带有 IN 子句的子查询:

SELECT ap.user_id, jt.id as jobId, date(app_date) AS appDate, jt.name AS title, count(*) AS `count`, at.*, a.*,ap.app_id
FROM applications ap
LEFT JOIN jobs j ON ap.job_id = j.job_id
LEFT JOIN job_titles jt ON jt.name = j.title
LEFT JOIN applicants a ON a.applicant_id = ap.user_id
LEFT JOIN applicant_tags at ON at.applicant_id = ap.user_id
LEFT JOIN tags t ON t.id = at.tag_id
WHERE ap.favorite = 1
AND (
    LOWER(jt.name) = LOWER('fisherman') OR 'fisherman' IN(SELECT jt.name FROM applicant_tags at 
    LEFT JOIN job_titles jt ON at.job_id = jt.id 
    WHERE at.applicant_id = a.applicant_id))
AND (LOWER(t.name) = LOWER('confident')
    OR LOWER(t.name) = LOWER('hard worker'))
GROUP BY ap.app_id
HAVING `count` = '2'
ORDER BY jt.name

谢谢大家的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    相关资源
    最近更新 更多