mysql - Rails 和查询 - 获取重复记录的自定义查询

标签 mysql sql ruby-on-rails ruby postgresql

在大多数情况下,我尽量不在我的应用程序中编写自定义 SQL 查询,但我遇到了一个案例,我想知道这是否是我最好这样做的案例。

我在这个特定的应用程序中使用 PostgreSQL。我只想返回已被重复预订任务的员工,这是我的模型。

我有以下模型。

用户

has_many :user_jobs

    Fields
    - id
    - name
    - address
    - phone

工作

has_many :user_jobs
has_many :users, through: :user_jobs

    Fields
    - id
    - date
    - start_time
    - end_time

用户工作

belongs_to :user
belongs_to :jobs

    Fields
    - id
    - job_id
    - user_id

Userjobs 是保存该工作的工作和雇员的表,但每个工作的日期和时间都保存在 Job 表中

我想返回类似的东西

user(employee) - 日期和时间 job1 - 日期和时间 job1

编辑:添加了更多架构细节

CREATE TABLE user_jobs (
    id integer NOT NULL,
    job_id integer,
    job_date date,
    notes text,
    job_rating integer,
    notes text,
    created_at timestamp without time zone,
    updated_at timestamp without time zone,
    user_id integer,
);


CREATE TABLE jobs (
    id integer NOT NULL,
    date date,
    start_time time without time zone,
    end_time time without time zone,
    notes text,
);


CREATE TABLE users (
    id integer NOT NULL,
    email character varying(255) DEFAULT ''::character varying NOT NULL,
    name character varying(255),
    address character varying(255),
    phone character varying(255),
    picture character varying(255),
    status character varying(255) DEFAULT 'active'::character varying,
);

提前致谢

最佳答案

Postgres 9.2+

这是一个粗糙的查询:

WITH alljobs AS(
  SELECT * FROM jobs j INNER JOIN user_jobs uj ON uj.job_id = j.id
) 
SELECT DISTINCT q1.user_id
FROM alljobs q1
JOIN alljobs q2 on
      q1.user_id = q2.user_id
  AND tsrange(q1.date + q1.start_time, q1.date + q1.end_time) && tsrange(q2.date + q2.start_time, q2.date + q2.end_time)

解释:

  • WITH alljobs 有效地分配变量名 alljobs到给定的查询。该查询只是所有具有开始和结束时间的工作分配的联合列表。
  • SELECT DISTINCT q1.user_id 仅返回重复预订的用户 ID。这在技术上是您所要求的,但您可能希望扩展此选择以获取更多有用的信息。我建议使用 SELECT *在调试时。
  • FROM alljobs q1 JOIN alljobs q2 这会将作业与自身相结合,这是将每个作业与其他作业进行比较所必需的。
  • q1.user_id = q2.user_id 我们只关心单个用户的碰撞。如果您想回答相关问题,例如“谁在一起工作?”,您可以更改此设置。
  • tsrange 一个postgres built-in range function从两个时间戳创建一个范围。日期和其他类型的时间戳也有类似的功能。 _这些范围类型仅在 9.2 中引入。
  • && 一个postgres range operator用于交叉路口。

Postgres <9.2

你可以替换tsrange&&使用您自己的交集逻辑,我认为它看起来像:q1.start_time < q2.start_time && q1.finish_time > q2.start_time OR q2.start_time < q1.start_time && q2.finish_time > q1.start_time . (同时添加 date。)

或者,由于您指定的开始时间始终相同,而这正是您真正关心的,在这种情况下您可以做一些更简单的事情:

SELECT user_id, date + start_time, COUNT(*)
FROM user_jobs INNER JOIN jobs ON job_id = jobs.id
GROUP BY user_id, date + start_time
HAVING COUNT(*) > 2

这将为您提供所有具有重复的用户 ID。要获得相应的作业,您可以将其包装在外部查询中。

SELECT user_jobs.user_id, user_jobs.job_id, jobs.date + jobs.start_time
FROM user_jobs INNER JOIN jobs ON job_id = jobs.id INNER JOIN (
  SELECT user_id, date + start_time, COUNT(*)
  FROM user_jobs INNER JOIN jobs ON job_id = jobs.id
  GROUP BY user_id, date + start_time
  HAVING COUNT(*) > 2
) dups ON dups.user_id = user_jobs.user_id
      AND dups.date + dups.start_time = job.date + jobs.start_time

架构建议

分开 date 会让您自己的生活变得更加困难和 time列。为什么不直接制作 start_timeend_time时间戳?这样您就不必总是将它们加在一起,您仍然可以通过强制转换来获取日期。

关于mysql - Rails 和查询 - 获取重复记录的自定义查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28031963/

相关文章:

java - 如何将 mysql 驱动程序 jar 添加到项目作为 github 存储库的依赖项?

php - mysqli_stmt_get_result 替代 php 5.2.6

ruby-on-rails - 确保表格单元格不会扩展以适合图像

javascript - Capybara 重定向到 JSON 响应

sql - 这个sql怎么写

mysql - mysql 中两点之间的距离不起作用?

c# - Linq 中这条 SQL 语句的等价物是什么?

sql - Postgres : delete rows order by without primary key

sql - 哪些索引有助于加快查询速度?

ruby-on-rails - Rails 3. 如何在编辑表单中显示两位小数?