[英]Rails and queries - Custom query to get duplicated records
在大多數情況下,我盡量不使用我的應用程序編寫自定義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
UserJobs
belongs_to :user
belongs_to :jobs
Fields
- id
- job_id
- user_id
Userjobs是保存工作和該工作的雇員的表,但是每個工作的日期和時間都保存在Job表中
我想返回類似
user(employee) - date and time job1 - date and time 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內置范圍函數 ,該函數從兩個時間戳創建一個范圍。 日期和其他類型的時間戳具有類似的功能。 _這些范圍類型僅在9.2中引入。 &&
一個postgres范圍運算符,用於交集。 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_time
和end_time
時間戳? 然后,您不必總是將它們加在一起,並且仍然可以通過強制轉換獲得日期。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.