简体   繁体   English

具有多个条件和子选择的SQL查询

[英]SQL query with multiple criteria and sub selects

I am fairly new to using joins and selecting from multiple tables. 对于使用联接并从多个表中进行选择,我还很陌生。 I have successfully figured out how to get data from 2 tables based on a number of conditions. 我已经成功地弄清楚了如何基于多种条件从2个表中获取数据。 Now my issue is that I need to return a count only if another condition is also met. 现在我的问题是,仅当还满足其他条件时,才需要返回一个计数。 The idea is like this: I have a query that returns the number of items in a specific status at a specific time. 这个想法是这样的:我有一个查询,该查询在特定时间返回处于特定状态的项目数。 My query for this is: 我对此的查询是:

SELECT count(*),
       e.campus_id,
       e.course_id
FROM statuses_history AS sh,
     enrolments AS e
WHERE sh.date_added > '2015-08-01 00:00:00'
  AND sh.date_added < '2015-08-20 23:59:59'
  AND sh.status_id = 57
  AND sh.item_id = e.enrolment_id
  AND (e.course_id = 2
       OR e.course_id =7
       OR e.course_id = 8
       OR e.course_id = 9)
GROUP BY e.campus_id,
         e.course_id;

Now I have to check that it has been in a different status, lets say sh.status_id = 50 before it was in 57. It also does not have to fall within the data range specified. 现在,我必须检查它是否处于其他状态,比如说sh.status_id = 50,然后它才是57。它也不必落在指定的数据范围内。 So I basically need to change my query in some way to also select if it's ever been in status_id 50 and then only return the result if both the statuses are found. 因此,我基本上需要以某种方式更改查询以选择它是否曾经在status_id 50中,然后仅在找到两个状态时才返回结果。 sh.status_id =57 will be bound by the dates specified. sh.status_id = 57将受指定日期的约束。

Thanks in advance for the help. 先谢谢您的帮助。

You can adjust the subselect as needed, but this will return a row if another value is found in the database. 您可以根据需要调整子选择,但是如果在数据库中找到另一个值,它将返回一行。

I don't like subselects, but this should work. 我不喜欢子选择,但这应该可行。 I have not tested the syntax. 我还没有测试语法。

select count(*), e.campus_id, e.course_id
FROM statuses_history as sh, enrolments as e
WHERE sh.date_added > '2015-08-01 00:00:00'
      AND sh.date_added < '2015-08-20 23:59:59'
      AND sh.status_id = 57
      AND sh.item_id = e.enrolment_id
      AND (e.course_id = 2 OR e.course_id =7
          OR e.course_id = 8 OR e.course_id = 9)
      AND EXISTS (select sh2.status_id from statuses_history as sh2
                 WHERE NOT sh2.status_id = 57
                   AND sh2.item_id = e.enrolment_id)
GROUP BY e.campus_id, e.course_id;

I assume that the primary key is item_id? 我假设主键是item_id?

You just have to join the same tables by the primary key and the status_id = 50. 您只需要通过主键和status_id = 50联接相同的表。

For this case I will use INNER JOIN (my preference) but you can use FROM/WHERE CLAUSE. 对于这种情况,我将使用INNER JOIN(我的偏好),但是您可以使用FROM / WHERE CLAUSE。

select count(*), e.campus_id, e.course_id  
FROM statuses_history as sh, enrolments as e

INNER JOIN statuses_history AS oldSh ON oldSh.item_id = sh.item_id AND oldSh.status_id = 50

WHERE sh.date_added > '2015-08-01 00:00:00' AND sh.date_added < '2015-08-20 23:59:59' AND sh.status_id = 57 and sh.item_id = e.enrolment_id AND (e.course_id = 2 OR e.course_id =7 OR e.course_id = 8 OR e.course_id = 9) 
GROUP BY e.campus_id, e.course_id;

But if you prefer WHERE, you can do the following: 但是,如果您更喜欢WHERE,则可以执行以下操作:

select count(*), e.campus_id, e.course_id  
FROM statuses_history as sh, enrolments as e, statuses_history AS oldSh ON  
WHERE oldSh.item_id = sh.item_id AND oldSh.status_id = 50 AND 
sh.date_added > '2015-08-01 00:00:00' AND sh.date_added < '2015-08-20 23:59:59' AND sh.status_id = 57 and sh.item_id = e.enrolment_id AND (e.course_id = 2 OR e.course_id =7 OR e.course_id = 8 OR e.course_id = 9) 
GROUP BY e.campus_id, e.course_id;

Add a left join and use a case statement to do your count. 添加左联接并使用case语句进行计数。

LEFT JOIN statuses_history sh2 ON sh2.item_id = e.enrollment_id AND sh2.status_id = 50

You'll need to use a different format for your inner joins in order to do the left join. 您需要对内部联接使用其他格式,以便进行左联接。 Here's the new query: 这是新的查询:

select count(sh.status_id), e.campus_id, e.course_id  , SUM(CASE WHEN sh2.status_id IS NOT NULL THEN 1 ELSE 0 END) as cnt
FROM statuses_history sh
INNER JOIN enrolments e ON sh.item_id = e.enrolment_id
LEFT JOIN statuses_history sh2 ON sh2.item_id = e.enrollment_id AND sh2.status_id = 50
WHERE sh.date_added > '2015-08-01 00:00:00' AND sh.date_added < '2015-08-20 23:59:59' AND sh.status_id = 57 AND (e.course_id = 2 OR e.course_id =7 OR e.course_id = 8 OR e.course_id = 9) 
GROUP BY e.campus_id, e.course_id;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM