简体   繁体   中英

SQL query to return records from one table that are associated to 2 records each from another table

I have 2 tables:

  1. Orders
+------------+
| Orders IDs |
+------------+
|      11462 |
|      25014 |
|      40328 |
+------------+
  1. Changes
+------------+------------+------------------+
| Orders IDs | Change IDs | Change Status    |
+------------+------------+------------------+
|      86351 |      18762 | archived         |
|      47622 |      19129 | pending_approval |
|      11462 |       3089 | draft            |
|      11462 |       3122 | draft            |
|      25014 |       6339 | draft            |
|      25014 |       6465 | draft            |
|      40328 |      14677 | draft            |
|      40328 |      14678 | draft            |
|      89901 |      19577 | approved         |
|      88413 |      19578 | pending_approval |
+------------+------------+------------------+

How do I query so that I am given a table containing order IDs that are associated to 2 changes that are in draft status? What query (ran against the table above) will return:

+------------+------------+---------------+
| Orders IDs | Change IDs | Change Status |
+------------+------------+---------------+
|      11462 |       3089 | draft         |
|      11462 |       3122 | draft         |
|      25014 |       6339 | draft         |
|      25014 |       6465 | draft         |
|      40328 |      14677 | draft         |
|      40328 |      14678 | draft         |
+------------+------------+---------------+

Thanks!

Use window functions:

select d.*
from (select d.*, count(*) over (partition by order_id, change_status) as cnt
      from drafts d
      where change_status = 'draft'
     ) d
where cnt = 2;

This can easily be modified if you really intend "2 or more".

Or, assuming that change_id is unique and you want 2 or more, use exists :

select d.*
from drafts d
where d.change_status = 'draft' and
      exists (select 1
              from drafts d2
              where d2.order_id = d.order_id and 
                    d2.change_status = 'draft' and
                    d2.change_id <> d.change_id
             );

Depending on what is it you exactly need you can do it like this:

SELECT * 
FROM changes
where Change_Status = 'draft'
order by Orders_IDs;

or like this:

select c.* 
from orders o
left join changes c
on o.Orders_IDs = c.Orders_IDs
where c.Change_Status = 'draft'
order by c.Orders_IDs;

here is a demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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