简体   繁体   English

SQL查询(Postgres)如何回答?

[英]SQL query (Postgres) how to answer that?

I have a table with company id's (non unique) and some attribute (let's call it status id), status can be between 1 to 18 (many to many the row id is what unique) now I need to get results of companies who only have rows with 1 and 18, if they have any number as well (let's say 3) then this company should not be returned.我有一个带有公司 ID(非唯一)和一些属性(我们称之为状态 ID)的表,状态可以在 1 到 18 之间(多对多行 ID 是唯一的),现在我需要获得公司的结果有 1 和 18 行,如果它们也有任何数字(假设为 3),则不应返回该公司。 The data is stored as row id, some meta data, company id and one status id, the example below is AFTER I ran a group by query.数据存储为行 id、一些元数据、公司 id 和一个状态 id,下面的示例是在我按查询运行组之后。

So as an example if I do group by and string agg, I am getting these values:例如,如果我按和字符串 agg 进行分组,我将得到以下值:

Company ID Status
1           1,9,12,18
2           12,13,18
3           1
4           8
5           18

So in this case I need to return only 3 and 5.所以在这种情况下,我只需要返回 3 和 5。

You should fix your data model.您应该修复您的数据模型。 Here are some reasons:以下是一些原因:

  • Storing numbers in strings is BAD.在字符串中存储数字是不好的。
  • Storing multiple values in a string is BAD.在一个字符串中存储多个值是不好的。
  • SQL has poor string processing capabilities. SQL 的字符串处理能力很差。
  • Postgres offers many ways to store multiple values -- a junction table, arrays, and JSON come to mind. Postgres 提供了多种存储多个值的方法——一个联结表、数组和 JSON 浮现在脑海中。

For your particular problem, how about an explicit comparison?对于您的特定问题,如何进行显式比较?

where status in ('1', '18', '1,18', '18,1')

You can group by companyid and set 2 conditions in the having clause:您可以group by companyid ,并设置2个条件having条款:

select companyid
from tablename
group by companyid
having 
  sum((status in (1, 18))::int) > 0
  and
  sum((status not in (1, 18))::int) = 0

Or with EXCEPT :或者EXCEPT

select companyid from tablename
except
select companyid from tablename
where status not in (1, 18)

See the demo .请参阅演示
Results:结果:

> | companyid |
> | --------: |
> |         3 |
> |         5 |

You can utilize group by and having.您可以使用 group by 和 have。 ie: IE:

select * 
from myTable 
where statusId in (1,18)
and companyId in (select companyId 
  from myTable 
  group by companyId
  having count(distinct statusId) = 1); 

EDIT: If you meant to include those who have 1,18 and 18,1 too, then you could use array_agg instead:编辑:如果您也打算包括那些有 1,18 和 18,1 的人,那么您可以改用 array_agg:

select *
from t t1
inner join
     (select companyId, array_agg(statusId) as statuses
      from t
      group by companyId
     ) t2 on t1.companyid = t2.companyid
where array[1,18] @> t2.statuses;

EDIT: If you meant to get back only companyIds without the rest of columns and data:编辑:如果您打算只取回 companyIds 而没有其余的列和数据:

select companyId
      from t
      group by companyId
      having array[1,18] @> array_agg(statusId);

DbFiddle Demo DbFiddle 演示

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

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